Skip to content

12. 리스트(List)와 튜플(Tuple) 응용


1. 키워드

  • 스택(Stack)과 큐(Queue)
  • 반복 가능한 객체(Iterable)
  • 리스트 표현식(List Comprehension)
  • 튜플 표현식(Tuple Comprehension)


2. 리스트와 튜플 응용하기

  • 파이썬의 리스트는 생각보다 기능이 많은데, 요소를 추가/삭제하거나, 정보를 조회하는 메서드도 제공한다.


3. 리스트 조작하기

1) 리스트에 요소 추가하기

  • 다음과 같이 리스트에 요소를 추가하는 메서드는 3가지가 있다.


1] append

  • 요소 하나를 추가

2] extend

  • 리스트를 연결하여 확장

3] insert

  • 특정 인덱스에 요소 추가


2) 리스트에 요소 하나 추가하기

  • append(요소)는 리스트 끝에 요소 하나를 추가한다.


>>> a = [10, 20, 30]

>>> a.append(500)

>>> a
[10, 20, 30, 500]

>>> len(a)
4


  • 물론 빈 리스트에 값을 추가할 수도 있다.


>>> a = []

>>> a.append(10)

>>> a
[10]


3) 리스트 안에 리스트 추가하기

  • append(리스트)처럼 리스트를 넣으면 리스트 안에 리스트가 들어간다.


>>> a = [10, 20, 30]

>>> a.append([500, 600])

>>> a
[10, 20, 30, [500, 600]]

>>> len(a)
4


  • append는 항상 리스트의 길이가 1씩 증가한다.


4) 리스트 확장하기

  • 리스트에 요소를 여러 개 추가하려면 append를 여러 번 사용하는 방법도 있지만, extend를 사용하면 간단하게 추가할 수 있다.


  • 다음과 같이 extend(리스트)는 리스트 끝에 다른 리스트를 연결하여 리스트를 확장한다.


>>> a = [10, 20, 30]

>>> a.extend([500, 600])

>>> a
[10, 20, 30, 500, 600]

>>> len(a)
5


5) 리스트의 특정 인덱스에 요소 추가하기

  • append, extend는 리스트 끝에 요소를 추가하지만, insert는 원하는 위치에 요소를 추가할 수 있다.


  • 다음과 같이 insert(인덱스, 요소)는 리스트의 특정 인덱스에 요소 하나를 추가한다.


>>> a = [10, 20, 30]

>>> a.insert(2, 500)

>>> a
[10, 20, 500, 30]

>>> len(a)
4


  • insert에서 자주 사용하는 패턴은 다음과 같다.


1] insert(0, 요소)

  • 리스트의 맨 처음에 요소를 추가

2] insert(len(리스트), 요소)

  • 리스트 끝에 요소를 추가


  • 다음은 리스트 [10, 20, 30]의 맨 처음에 500을 추가한다.


>>> a = [10, 20, 30]

>>> a.insert(0, 500)

>>> a
[500, 10, 20, 30]


  • 그리고 다음과 같이 insert에 마지막 인덱스보다 큰 값을 지정하면 리스트 끝에 요소 하나를 추가할 수 있다.


>>> a = [10, 20, 30]

>>> a.insert(len(a), 500)

>>> a
[10, 20, 30, 500]


  • len(리스트)는 마지막 인덱스보다 1이 더 크기 때문에 리스트 끝에 값을 추가할 때 자주 활용한다.
  • 하지만 사실 이 방법은 a.append(500)과 같다.


  • 특히 insert는 요소 하나를 추가하므로 insert에 리스트를 넣으면 append처럼 리스트 안에 리스트가 들어간다.


>>> a = [10, 20, 30]

>>> a.insert(1, [500, 600])

>>> a
[10, [500, 600], 20, 30]


  • 만약 리스트 중간에 요소 여러 개를 추가하고 싶다면 슬라이스를 활용하면 된다.


>>> a = [10, 20, 30]

>>> a[1:1] = [500, 600]

>>> a
[10, 500, 600, 20, 30]


  • a[1:1] = [500, 600]과 같이 시작 인덱스와 끝 인덱스를 같게 지정하면 해당 인덱스의 요소를 덮어쓰지 않으면서 요소 여러 개를 중간에 추가할 수 있다.


6) 리스트에서 요소 삭제하기

  • 요소를 삭제하는 메서드는 다음과 같다.


1] pop

  • 마지막 요소 또는 특정 인덱스의 요소를 삭제

2] remove

  • 특정 값을 찾아서 삭제


7) 리스트에서 특정 인덱스의 요소를 삭제하기

  • pop()은 리스트의 마지막 요소를 삭제한 뒤 삭제한 요소를 반환한다.


>>> a = [10, 20, 30]

>>> a.pop()
30

>>> a
[10, 20]


  • pop(인덱스)는 해당 인덱스의 요소를 삭제한 뒤 삭제한 요소를 반환한다.


>>> a = [10, 20, 30]

>>> a.pop(1)
20

>>> a
[10, 30]


  • pop 대신 del을 사용해도 상관없다.


>>> a = [10, 20, 30]

>>> del a[1]

>>> a
[10, 30]


8) 리스트에서 특정 값을 찾아서 삭제하기

  • 리스트에서 원하는 값을 찾아서 삭제하려면 remove를 사용하면 된다.


>>> a = [10, 20, 30]

>>> a.remove(20)

>>> a
[10, 30]


  • 만약 리스트에 같은 값이 여러 개 있을 경우 처음 찾은 값을 삭제한다.


>>> a = [10, 20, 30, 20]

>>> a.remove(20)

>>> a
[10, 30, 20]


  • 리스트 a20이 2개 있지만 가장 처음 찾은 인덱스 120만 삭제한다.


리스트로 스택과 큐 만들기

  • 지금까지 알아본 리스트의 메서드로 스택(Stack)과 큐(Queue)를 만들 수 있다.


  • 다음과 같이 appendpop을 호출하는 그림을 90도 돌리면 스택의 모습이 된다.


001


  • 여기서 pop() 대신 pop(0)을 사용하면 큐가 된다.


002


  • 물론 append(), pop(0)이 아닌 insert(0, 요소), pop()을 사용해서 추가/삭제 방향을 반대로 해도 큐가 된다.
  • 파이썬에서 스택은 리스트를 그대로 활용해도 되지만, 큐는 좀 더 효율적으로 사용할 수 있도록 deque라는 클래스를 제공한다.
  • deque는 양쪽 끝에서 추가/삭제가 가능한 클래스이다.


deque(반복가능한객체)
>>> from collections import deque

>>> a = deque([10, 20, 30])
>>> a
deque([10, 20, 30])

>>> a.append(500)
>>> a
deque([10, 20, 30, 500])

>>> a.popleft()
10
>>> a
deque([20, 30, 500])


  • dequeappend는 오른쪽에 요소를 추가하고, popleft는 왼쪽 요소를 삭제한다.
  • 반대로 appendleft는 왼쪽에 요소를 추가하고, pop은 오른쪽 요소를 삭제한다.


9) 리스트에서 특정 값의 인덱스 구하기

  • index(값)은 리스트에서 특정 값의 인덱스를 구한다.


>>> a = [10, 20, 30, 15, 20, 40]

>>> a.index(20)
1


  • 이때 같은 값이 여러 개일 경우 처음 찾은 인덱스를 구한다.


10) 특정 값의 개수 구하기

  • count(값)은 리스트에서 특정 값의 개수를 구한다.


>>> a = [10, 20, 30, 15, 20, 40]

>>> a.count(20)
2


  • 리스트 a에는 20이 2개 들어있으므로 2가 나온다.


11) 리스트의 순서를 뒤집기

  • reverse()는 리스트에서 요소의 순서를 반대로 뒤집는다.


>>> a = [10, 20, 30, 15, 20, 40]

>>> a.reverse()

>>> a
[40, 20, 15, 30, 20, 10]


12) 리스트의 요소를 정렬하기

  • sort()는 리스트의 요소를 작은 순서대로 정렬한다(오름차순).


1] sort() 또는 sort(reverse=False)

  • 리스트의 값을 작은 순서대로 정렬(오름차순)

2] sort(reverse=True)

  • 리스트의 값을 큰 순서대로 정렬(내림차순)


>>> a = [10, 20, 30, 15, 20, 40]

>>> a.sort()

>>> a
[10, 15, 20, 20, 30, 40]


sort 메서드와 sorted 함수

  • 파이썬은 리스트의 sort 메서드뿐만 아니라 내장 함수 sorted도 제공한다.
  • sort는 메서드를 사용한 리스트를 변경하지만, sorted 함수는 정렬된 새 리스트를 생성한다.


>>> a = [10, 20, 30, 15, 20, 40]
>>> a.sort()
>>> a
[10, 15, 20, 20, 30, 40]

>>> b = [10, 20, 30, 15, 20, 40]
>>> sorted(b)
[10, 15, 20, 20, 30, 40]


13) 리스트의 모든 요소를 삭제하기

  • clear()는 리스트의 모든 요소를 삭제한다.


>>> a = [10, 20, 30]

>>> a.clear()

>>> a
[]


  • clear 대신 del a[:]와 같이 시작, 끝 인덱스를 생략하여 리스트의 모든 요소를 삭제할 수도 있다.


>>> a = [10, 20, 30]

>>> del a[:]

>>> a
[]


14) 리스트를 슬라이스로 조작하기

  • 다음과 같이 리스트 끝에 값이 한 개 들어있는 리스트를 추가할 수 있다.


>>> a = [10, 20, 30]

>>> a[len(a):] = [500]

>>> a
[10, 20, 30, 500]


  • 다음과 같이 요소가 여러 개 들어있는 리스트를 연결할 수 있다.


>>> a = [10, 20, 30]

>>> a[len(a):] = [500, 600]

>>> a
[10, 20, 30, 500, 600]


  • a[len(a):] = [500, 600]a.extend([500, 600])과 같다.


리스트가 비어 있는지 확인하기

  • 리스트(시퀀스 객체가) 비어 있는지 확인하려면 if 조건문과 len 함수로 길이를 판단하면 된다.


if not len(seq): # 리스트가 비어 있으면 True
if len(seq): # 리스트에 요소가 있으면 True


  • 하지만 파이썬에서는 위의 방법보다 리스트(시퀀스 객체)를 바로 if 조건문으로 판단하는 방법을 권장한다.


if not seq: # 리스트가 비어 있으면 True
if seq: # 리스트에 내용이 있으면 True


4. 리스트의 할당과 복사 알아보기

  • 할당과 복사는 비슷한 것 같지만 큰 차이점이 있다.


  • 먼저 다음과 같이 리스트를 만든 뒤 다른 변수에 할당한다.


>>> a = [0, 0, 0, 0, 0]

>>> b = a


  • b = a와 같이 리스트를 다른 변수에 할당하면 리스트는 두 개가 될 것 같지만 실제로는 리스트가 한 개이다.


003


  • abis 연산자로 비교해 보면 True가 나온다.
  • 즉, 변수 이름만 다를 뿐 리스트 ab는 같은 객체이다.


>>> a is b
True


  • ab는 같으므로 b[2] = 99와 같이 리스트 b의 요소를 변경하면 리스트 ab에 모두 반영된다.


>>> b[2] = 99

>>> a
[0, 0, 99, 0, 0]
>>> b
[0, 0, 99, 0, 0]


004


  • 리스트 ab를 완전히 다른 두 개로 만들려면 copy 메서드로 모든 요소를 복사해야 한다.


>>> a = [0, 0, 0, 0, 0]

>>> b = a.copy()


  • b = a.copy()와 같이 copy를 사용한 뒤 b에 할당해 주면 리스트 a의 요소가 모두 b에 복사된다.


005


  • abis 연산자로 비교해 보면 False가 나오며, 두 리스트는 다른 객체라는 것을 의미한다.
  • 하지만 복사된 요소는 모두 같으므로 ==로 비교하면 True가 나온다.


>>> a is b
False

>>> a == b
True


  • 이제 리스트 ab는 별개이므로 한쪽의 값을 변경해도 다른 리스트에 영향을 미치지 않는다.


  • 다음과 같이 리스트 b의 요소를 변경하면 리스트 a는 그대로이고 리스트 b만 바뀐다.


>>> b[2] = 99

>>> a
[0, 0, 0, 0, 0]
>>> b
[0, 0, 99, 0, 0]


006


5. 반복문으로 리스트의 요소를 모두 출력하기

  • 리스트와 반복문을 사용하여 간단하게 모든 요소를 출력할 수 있다.


1) for 반복문으로 요소 출력하기

  • for 반복문은 in 뒤에 리스트를 지정하면 된다.


for 변수 in 리스트:
    반복할코드


  • 다음은 for로 리스트 a의 모든 요소를 출력한다.


>>> a = [38, 21, 53, 62, 19]

>>> for i in a:
...     print(i)
...
38
21
53
62
19


  • for i in a:는 리스트 a에서 요소를 꺼내서 i에 저장하고, 꺼낼 때마다 코드를 반복한다.
  • 따라서 printi를 출력하면 모든 요소를 순서대로 출력할 수 있다.


  • 물론 다음과 같이 in 다음에 리스트를 직접 지정해도 상관없다.


for i in [38, 21, 53, 62, 19]:
    print(i)


2) 인덱스와 요소를 함께 출력하기

  • for 반복문으로 요소를 출력할 때 인덱스도 함께 출력하려면 enumerate를 사용하면 된다.


for 인덱스, 요소 in enumerate(리스트):
>>> a = [38, 21, 53, 62, 19]

>>> for index, value in enumerate(a):
...     print(index, value)
...
0 38
1 21
2 53
3 62
4 19


  • for index, value in enumerate(a):와 같이 enumerate에 리스트를 넣으면 for 반복문에서 인덱스와 요소를 동시에 꺼내올 수 있다.


  • 인덱스를 0이 아닌 1부터 출력하려면 다음과 같이 index + 1을 출력하면 된다.


>>> for index, value in enumerate(a):
...     print(index + 1, value)
...
1 38
2 21
3 53
4 62
5 19


  • 또한 다음과 같이 enumeratestart를 지정할 수도 있다.


for 인덱스, 요소 in enumerate(리스트, start=숫자):
>>> for index, value in enumerate(a, start=1):
...     print(index, value)
...
1 38
2 21
3 53
4 62
5 19


for 반복문에서 인덱스로 요소를 출력하기

  • rangelen으로 리스트의 길이(요소 개수)를 구해서 넣어주면 인덱스를 순서대로 만들어준다.


>>> a = [38, 21, 53, 62, 19]

>>> for i in range(len(a)):
...     print(a[i])
...
38
21
53
62
19


3) while 반복문으로 요소 출력하기

  • while 반복문으로 리스트의 요소를 출력해 보자.


>>> a = [38, 21, 53, 62, 19]

>>> i = 0

>>> while i < len(a):
...     print(a[i])
...     i += 1
...
38
21
53
62
19


  • while 반복문으로 리스트의 요소를 출력할 때는 변수 i를 인덱스로 활용한다.
  • 먼저 변수 i0으로 만들어주고 i < len(a)처럼 i가 리스트의 길이(요소 개수) 직전까지만 반복하도록 만든다.


6. 리스트의 가장 작은 수, 가장 큰 수, 합계 구하기

  • 파이썬에서 제공하는 min, max 함수를 사용하여 가장 작은 수와 가장 큰 수를 찾을 수 있다.


>>> a = [38, 21, 53, 62, 19]

>>> min(a)
19
>>> max(a)
62


1) 요소의 합계 구하기

  • 파이썬에서는 합계를 구하는 sum 함수를 제공한다.


>>> a = [10, 10, 10, 10, 10]

>>> sum(a)
50


  • 이처럼 sum에 리스트를 넣어서 간단하게 요소의 합계를 구할 수 있다.
  • min, max, sum에는 리스트뿐만 아니라 모든 반복 가능한 객체(Iterable)를 넣을 수 있다.


7. 리스트 표현식 사용하기

  • 리스트 안에 식, for 반복문, if 조건문 등을 지정하여 리스트를 생성하는 것을 리스트 표현식(List Comprehension)이라고 한다.
  • 리스트 표현식은 식으로 지정해서 생성된 것을 리스트로 잡아두는 것을 의미한다.


  • 리스트 표현식은 다음과 같이 리스트 안에 식, for 반복문을 지정한다.


[ for 변수 in 리스트]
list( for 변수 in 리스트)
>>> a = [i for i in range(10)]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> b = list(i for i in range(10))
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


007


  • [i for i in range(10)]은 변수 i를 그대로 사용하지만, 다음과 같이 식 부분에서 i를 다른 값과 연산하면 각 연산의 결과를 리스트로 생성한다.


>>> c = [i + 5 for i in range(10)]
>>> c
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

>>> d = [i * 2 for i in range(10)]
>>> d
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]


  • 식을 [i + 5 for i in range(10)]과 같이 i5를 더하면 0부터 9까지의 숫자에 5를 더한 값으로 리스트를 생성한다.
  • 마찬가지로 [i * 2 for i in range(10)]0부터 9까지의 숫자에 2를 곱한 값으로 리스트를 생성한다.


대괄호와 list() 리스트 표현식

  • 리스트 표현식은 [식 for 변수 in 리스트]처럼 [](대괄호)로 만들 수도 있고, list(식 for 변수 in 리스트)처럼 list로 만들 수도 있다.
  • 둘 중에 성능은 대괄호 방식이 더 좋다.


1) 리스트 표현식에서 if 조건문 사용하기

  • if 조건문은 for 반복문 뒤에 지정한다.


[ for 변수 in 리스트 if 조건식]
list( for 변수 in 리스트 if 조건식)
>>> a = [i for i in range(10) if i % 2 == 0]

>>> a
[0, 2, 4, 6, 8]


  • [i for i in range(10) if i % 2 == 0]0부터 9까지 숫자를 생성하여 2의 배수인 숫자(짝수)로만 리스트를 생성한다.
  • 즉, 다음과 같이 for 반복문 뒤에 if 조건문을 지정하면 숫자를 생성한 뒤 if 조건문에서 특정 숫자만 뽑아내서 리스트를 생성한다.


008


  • 물론 다음과 같이 i를 다른 값과 연산해서 리스트를 만들어도 된다.


>>> b = [i + 5 for i in range(10) if i % 2 == 1]

>>> b
[6, 8, 10, 12, 14]


2) for 반복문과 if 조건문을 여러 번 사용하기

  • 리스트 표현식은 forif를 여러 번 사용할 수도 있다.


[ for 변수1 in 리스트1 if 조건식1 for 변수2 in 리스트2 if 조건식2 ... for 변수n in 리스트n if 조건식n]
list( for 변수1 in 리스트1 if 조건식1 for 변수2 in 리스트2 if 조건식2 ... for 변수n in 리스트n if 조건식n)


  • 다음은 2단부터 9단까지 구구단을 리스트로 생성한다.


>>> a = [i * j for j in range(2, 10) for i in range(1, 10)]

>>> a
[2, 4, 6, 8, 10, 12, 14, 16, 18, 3, 6, 9, 12, 15, 18, 21, 24, 27, 4, 8, 12, 16, 20, 24, 28, 32, 36, 5, 10, 15, 20, 25, 30, 35, 40, 45, 6, 12, 18, 24, 30, 36, 42, 48, 54, 7, 14, 21, 28, 35, 42, 49, 56, 63, 8, 16, 24, 32, 40, 48, 56, 64, 72, 9, 18, 27, 36, 45, 54, 63, 72, 81]


  • 여기서는 코드를 한 줄로 입력했지만 다음과 같이 여러 줄로 입력해도 된다.


a = [i * j for j in range(2, 10)
           for i in range(1, 10)]


  • 리스트 표현식에 for가 여러 개일 때 처리 순서는 뒤에서 앞으로 순이다.


009


8. 리스트에 map 사용하기

  • map은 리스트의 요소를 지정된 함수로 처리해 주는 함수이다.
  • map은 원본 리스트를 변경하지 않고 새 리스트를 생성한다.


list(map(함수, 리스트))
tuple(map(함수, 튜플))


  • 다음과 같이 map을 사용할 수 있다.


>>> a = [1.2, 2.5, 3.7, 4.6]

>>> a = list(map(int, a))

>>> a
[1, 2, 3, 4]


  • a = list(map(int, a)) 한 줄로 변환이 끝났다.
  • mapint와 리스트를 넣으면 리스트의 모든 요소를 int를 사용해서 변환한다.
  • 그 다음 list를 사용해서 map의 결과를 다시 리스트로 만들어준다.


010


  • 다음과 같이 map에는 리스트뿐만 아니라 모든 반복 가능한 객체를 넣을 수 있다.


>>> a = list(map(str, range(10)))

>>> a
['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']


  • range0부터 9까지 숫자를 만들고, str을 이용해서 모두 문자열로 변환했다.


1) input().split()map

  • input().split()의 결과가 문자열 리스트라서 map을 사용할 수 있다.


>>> a = input().split()
10 20 (입력)

>>> a
['10', '20']


  • 이제 map을 사용해서 정수로 변환해 보자.


>>> a = list(map(int, input().split()))
10 20 (입력)

>>> a
[10, 20]


  • 맵 객체를 list를 이용하여 리스트로 출력했다.


  • 또한 다음과 같이 map이 반환하는 맵 객체는 Iterator이기 때문에 변수 여러 개에 저장하는 언패킹이 가능하다.


x = input().split()

m = map(int, x)

a, b = m


9. 튜플 응용하기

  • 튜플은 리스트와 달리 내용을 변경할 수 없는 Immutable 클래스이다.
  • 따라서 내용을 변경하는 append 같은 메서드는 사용할 수 없고, 요소의 정보를 구하는 메서드만 사용할 수 있다.


1) 튜플에서 특정 값의 인덱스 구하기

  • index(값)은 튜플에서 특정 값의 인덱스를 구한다.
  • 이때 같은 값이 여러 개일 경우 처음 찾은 인덱스를 구한다.


>>> a = (38, 21, 53, 62, 19, 53)

>>> a.index(53)
2


2) 특정 값의 개수 구하기

  • count(값)은 튜플에서 특정 값의 개수를 구한다.


>>> a = (10, 20, 30, 15, 20, 40)

>>> a.count(20)
2


3) for 반복문으로 요소 출력하기

  • for 반복문으로 요소를 출력하는 방법은 리스트와 같다.


>>> a = (38, 21, 53, 62, 19)

>>> for i in a:
...     print(i, end=" ")
...
38 21 53 62 19


4) 튜플 표현식 사용하기

  • 튜플을 리스트 표현식처럼 생성할 때는 다음과 같이 tuple 안에 for 반복문과 if 조건문을 지정한다.


tuple( for 변수 in 리스트 if 조건식)
>>> a = tuple(i for i in range(10) if i % 2 == 0)

>>> a
(0, 2, 4, 6, 8)


  • 참고로 ()(괄호) 안에 표현식을 넣으면 튜플이 아니라 제너레이터 표현식이 된다.


>>> (i for i in range(10) if i % 2 == 0)
<generator object <genexpr> at ...>


5) tuplemap 사용하기

  • 튜플에 map을 사용하는 방법도 리스트와 같다.


>>> a = (1.2, 2.5, 3.7, 4.6)

>>> a = tuple(map(int, a))

>>> a
(1, 2, 3, 4)


6) 튜플에서 가장 작은 수, 가장 큰 수, 합계 구하기

  • 튜플도 min, max 함수로 가장 작은 수와 가장 큰 수를 구하고, sum 함수로 요소의 합계를 구할 수 있다.


>>> a = (38, 21, 53, 62, 19)

>>> min(a)
19
>>> max(a)
62
>>> sum(a)
193

References