12. 리스트(List)와 튜플(Tuple) 응용
1. 키워드
- 스택(Stack)과 큐(Queue)
- 반복 가능한 객체(Iterable)
- 리스트 표현식(List Comprehension)
- 튜플 표현식(Tuple Comprehension)
2. 리스트와 튜플 응용하기
- 파이썬의 리스트는 생각보다 기능이 많은데, 요소를 추가/삭제하거나, 정보를 조회하는 메서드도 제공한다.
3. 리스트 조작하기
1) 리스트에 요소 추가하기
- 다음과 같이 리스트에 요소를 추가하는 메서드는 3가지가 있다.
1] append
- 요소 하나를 추가
2] extend
- 리스트를 연결하여 확장
3] insert
- 특정 인덱스에 요소 추가
2) 리스트에 요소 하나 추가하기
append(요소)
는 리스트 끝에 요소 하나를 추가한다.
- 물론 빈 리스트에 값을 추가할 수도 있다.
3) 리스트 안에 리스트 추가하기
append(리스트)
처럼 리스트를 넣으면 리스트 안에 리스트가 들어간다.
append
는 항상 리스트의 길이가 1씩 증가한다.
4) 리스트 확장하기
- 리스트에 요소를 여러 개 추가하려면
append
를 여러 번 사용하는 방법도 있지만,extend
를 사용하면 간단하게 추가할 수 있다.
- 다음과 같이
extend(리스트)
는 리스트 끝에 다른 리스트를 연결하여 리스트를 확장한다.
5) 리스트의 특정 인덱스에 요소 추가하기
append
,extend
는 리스트 끝에 요소를 추가하지만,insert
는 원하는 위치에 요소를 추가할 수 있다.
- 다음과 같이
insert(인덱스, 요소)
는 리스트의 특정 인덱스에 요소 하나를 추가한다.
insert
에서 자주 사용하는 패턴은 다음과 같다.
1] insert(0, 요소)
- 리스트의 맨 처음에 요소를 추가
2] insert(len(리스트), 요소)
- 리스트 끝에 요소를 추가
- 다음은 리스트
[10, 20, 30]
의 맨 처음에500
을 추가한다.
- 그리고 다음과 같이
insert
에 마지막 인덱스보다 큰 값을 지정하면 리스트 끝에 요소 하나를 추가할 수 있다.
len(리스트)
는 마지막 인덱스보다1
이 더 크기 때문에 리스트 끝에 값을 추가할 때 자주 활용한다.- 하지만 사실 이 방법은
a.append(500)
과 같다.
- 특히
insert
는 요소 하나를 추가하므로insert
에 리스트를 넣으면append
처럼 리스트 안에 리스트가 들어간다.
- 만약 리스트 중간에 요소 여러 개를 추가하고 싶다면 슬라이스를 활용하면 된다.
a[1:1] = [500, 600]
과 같이 시작 인덱스와 끝 인덱스를 같게 지정하면 해당 인덱스의 요소를 덮어쓰지 않으면서 요소 여러 개를 중간에 추가할 수 있다.
6) 리스트에서 요소 삭제하기
- 요소를 삭제하는 메서드는 다음과 같다.
1] pop
- 마지막 요소 또는 특정 인덱스의 요소를 삭제
2] remove
- 특정 값을 찾아서 삭제
7) 리스트에서 특정 인덱스의 요소를 삭제하기
pop()
은 리스트의 마지막 요소를 삭제한 뒤 삭제한 요소를 반환한다.
pop(인덱스)
는 해당 인덱스의 요소를 삭제한 뒤 삭제한 요소를 반환한다.
- pop 대신 del을 사용해도 상관없다.
8) 리스트에서 특정 값을 찾아서 삭제하기
- 리스트에서 원하는 값을 찾아서 삭제하려면
remove
를 사용하면 된다.
- 만약 리스트에 같은 값이 여러 개 있을 경우 처음 찾은 값을 삭제한다.
- 리스트
a
에20
이 2개 있지만 가장 처음 찾은 인덱스1
의20
만 삭제한다.
리스트로 스택과 큐 만들기
- 지금까지 알아본 리스트의 메서드로 스택(Stack)과 큐(Queue)를 만들 수 있다.
- 다음과 같이
append
와pop
을 호출하는 그림을 90도 돌리면 스택의 모습이 된다.
- 여기서
pop()
대신pop(0)
을 사용하면 큐가 된다.
- 물론
append()
,pop(0)
이 아닌insert(0, 요소)
,pop()
을 사용해서 추가/삭제 방향을 반대로 해도 큐가 된다. - 파이썬에서 스택은 리스트를 그대로 활용해도 되지만, 큐는 좀 더 효율적으로 사용할 수 있도록
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])
deque
의append
는 오른쪽에 요소를 추가하고,popleft
는 왼쪽 요소를 삭제한다.- 반대로
appendleft
는 왼쪽에 요소를 추가하고,pop
은 오른쪽 요소를 삭제한다.
9) 리스트에서 특정 값의 인덱스 구하기
index(값)
은 리스트에서 특정 값의 인덱스를 구한다.
- 이때 같은 값이 여러 개일 경우 처음 찾은 인덱스를 구한다.
10) 특정 값의 개수 구하기
count(값)
은 리스트에서 특정 값의 개수를 구한다.
- 리스트
a
에는20
이 2개 들어있으므로2
가 나온다.
11) 리스트의 순서를 뒤집기
reverse()
는 리스트에서 요소의 순서를 반대로 뒤집는다.
12) 리스트의 요소를 정렬하기
sort()
는 리스트의 요소를 작은 순서대로 정렬한다(오름차순).
1] sort()
또는 sort(reverse=False)
- 리스트의 값을 작은 순서대로 정렬(오름차순)
2] sort(reverse=True)
- 리스트의 값을 큰 순서대로 정렬(내림차순)
sort
메서드와 sorted
함수
- 파이썬은 리스트의
sort
메서드뿐만 아니라 내장 함수sorted
도 제공한다. sort
는 메서드를 사용한 리스트를 변경하지만,sorted
함수는 정렬된 새 리스트를 생성한다.
13) 리스트의 모든 요소를 삭제하기
clear()
는 리스트의 모든 요소를 삭제한다.
clear
대신del a[:]
와 같이 시작, 끝 인덱스를 생략하여 리스트의 모든 요소를 삭제할 수도 있다.
14) 리스트를 슬라이스로 조작하기
- 다음과 같이 리스트 끝에 값이 한 개 들어있는 리스트를 추가할 수 있다.
- 다음과 같이 요소가 여러 개 들어있는 리스트를 연결할 수 있다.
a[len(a):] = [500, 600]
은a.extend([500, 600])
과 같다.
리스트가 비어 있는지 확인하기
- 리스트(시퀀스 객체가) 비어 있는지 확인하려면
if
조건문과len
함수로 길이를 판단하면 된다.
- 하지만 파이썬에서는 위의 방법보다 리스트(시퀀스 객체)를 바로
if
조건문으로 판단하는 방법을 권장한다.
4. 리스트의 할당과 복사 알아보기
- 할당과 복사는 비슷한 것 같지만 큰 차이점이 있다.
- 먼저 다음과 같이 리스트를 만든 뒤 다른 변수에 할당한다.
b = a
와 같이 리스트를 다른 변수에 할당하면 리스트는 두 개가 될 것 같지만 실제로는 리스트가 한 개이다.
a
와b
를is
연산자로 비교해 보면True
가 나온다.- 즉, 변수 이름만 다를 뿐 리스트
a
와b
는 같은 객체이다.
a
와b
는 같으므로b[2] = 99
와 같이 리스트b
의 요소를 변경하면 리스트a
와b
에 모두 반영된다.
- 리스트
a
와b
를 완전히 다른 두 개로 만들려면copy
메서드로 모든 요소를 복사해야 한다.
b = a.copy()
와 같이copy
를 사용한 뒤b
에 할당해 주면 리스트a
의 요소가 모두b
에 복사된다.
a
와b
를is
연산자로 비교해 보면False
가 나오며, 두 리스트는 다른 객체라는 것을 의미한다.- 하지만 복사된 요소는 모두 같으므로
==
로 비교하면True
가 나온다.
- 이제 리스트
a
와b
는 별개이므로 한쪽의 값을 변경해도 다른 리스트에 영향을 미치지 않는다.
- 다음과 같이 리스트
b
의 요소를 변경하면 리스트a
는 그대로이고 리스트b
만 바뀐다.
5. 반복문으로 리스트의 요소를 모두 출력하기
- 리스트와 반복문을 사용하여 간단하게 모든 요소를 출력할 수 있다.
1) for
반복문으로 요소 출력하기
for
반복문은in
뒤에 리스트를 지정하면 된다.
- 다음은
for
로 리스트a
의 모든 요소를 출력한다.
for i in a:
는 리스트a
에서 요소를 꺼내서i
에 저장하고, 꺼낼 때마다 코드를 반복한다.- 따라서
print
로i
를 출력하면 모든 요소를 순서대로 출력할 수 있다.
- 물론 다음과 같이
in
다음에 리스트를 직접 지정해도 상관없다.
2) 인덱스와 요소를 함께 출력하기
for
반복문으로 요소를 출력할 때 인덱스도 함께 출력하려면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
을 출력하면 된다.
- 또한 다음과 같이
enumerate
에start
를 지정할 수도 있다.
for
반복문에서 인덱스로 요소를 출력하기
range
에len
으로 리스트의 길이(요소 개수)를 구해서 넣어주면 인덱스를 순서대로 만들어준다.
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
를 인덱스로 활용한다.- 먼저 변수
i
를0
으로 만들어주고i < len(a)
처럼i
가 리스트의 길이(요소 개수) 직전까지만 반복하도록 만든다.
6. 리스트의 가장 작은 수, 가장 큰 수, 합계 구하기
- 파이썬에서 제공하는
min
,max
함수를 사용하여 가장 작은 수와 가장 큰 수를 찾을 수 있다.
1) 요소의 합계 구하기
- 파이썬에서는 합계를 구하는
sum
함수를 제공한다.
- 이처럼
sum
에 리스트를 넣어서 간단하게 요소의 합계를 구할 수 있다. min
,max
,sum
에는 리스트뿐만 아니라 모든 반복 가능한 객체(Iterable)를 넣을 수 있다.
7. 리스트 표현식 사용하기
- 리스트 안에 식,
for
반복문,if
조건문 등을 지정하여 리스트를 생성하는 것을 리스트 표현식(List Comprehension)이라고 한다. - 리스트 표현식은 식으로 지정해서 생성된 것을 리스트로 잡아두는 것을 의미한다.
- 리스트 표현식은 다음과 같이 리스트 안에 식,
for
반복문을 지정한다.
>>> 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]
[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)]
과 같이i
에5
를 더하면0
부터9
까지의 숫자에5
를 더한 값으로 리스트를 생성한다. - 마찬가지로
[i * 2 for i in range(10)]
은0
부터9
까지의 숫자에2
를 곱한 값으로 리스트를 생성한다.
대괄호와 list()
리스트 표현식
- 리스트 표현식은
[식 for 변수 in 리스트]
처럼[]
(대괄호)로 만들 수도 있고,list(식 for 변수 in 리스트)
처럼list
로 만들 수도 있다. - 둘 중에 성능은 대괄호 방식이 더 좋다.
1) 리스트 표현식에서 if
조건문 사용하기
if
조건문은for
반복문 뒤에 지정한다.
[i for i in range(10) if i % 2 == 0]
은0
부터9
까지 숫자를 생성하여2
의 배수인 숫자(짝수)로만 리스트를 생성한다.- 즉, 다음과 같이
for
반복문 뒤에if
조건문을 지정하면 숫자를 생성한 뒤if
조건문에서 특정 숫자만 뽑아내서 리스트를 생성한다.
- 물론 다음과 같이
i
를 다른 값과 연산해서 리스트를 만들어도 된다.
2) for
반복문과 if
조건문을 여러 번 사용하기
- 리스트 표현식은
for
와if
를 여러 번 사용할 수도 있다.
[식 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]
- 여기서는 코드를 한 줄로 입력했지만 다음과 같이 여러 줄로 입력해도 된다.
- 리스트 표현식에
for
가 여러 개일 때 처리 순서는 뒤에서 앞으로 순이다.
8. 리스트에 map
사용하기
map
은 리스트의 요소를 지정된 함수로 처리해 주는 함수이다.map
은 원본 리스트를 변경하지 않고 새 리스트를 생성한다.
- 다음과 같이
map
을 사용할 수 있다.
a = list(map(int, a))
한 줄로 변환이 끝났다.map
에int
와 리스트를 넣으면 리스트의 모든 요소를int
를 사용해서 변환한다.- 그 다음
list
를 사용해서map
의 결과를 다시 리스트로 만들어준다.
- 다음과 같이
map
에는 리스트뿐만 아니라 모든 반복 가능한 객체를 넣을 수 있다.
range
로0
부터9
까지 숫자를 만들고,str
을 이용해서 모두 문자열로 변환했다.
1) input().split()
과 map
input().split()
의 결과가 문자열 리스트라서map
을 사용할 수 있다.
- 이제
map
을 사용해서 정수로 변환해 보자.
- 맵 객체를
list
를 이용하여 리스트로 출력했다.
- 또한 다음과 같이
map
이 반환하는 맵 객체는 Iterator이기 때문에 변수 여러 개에 저장하는 언패킹이 가능하다.
9. 튜플 응용하기
- 튜플은 리스트와 달리 내용을 변경할 수 없는 Immutable 클래스이다.
- 따라서 내용을 변경하는
append
같은 메서드는 사용할 수 없고, 요소의 정보를 구하는 메서드만 사용할 수 있다.
1) 튜플에서 특정 값의 인덱스 구하기
index(값)
은 튜플에서 특정 값의 인덱스를 구한다.- 이때 같은 값이 여러 개일 경우 처음 찾은 인덱스를 구한다.
2) 특정 값의 개수 구하기
count(값)
은 튜플에서 특정 값의 개수를 구한다.
3) for
반복문으로 요소 출력하기
for
반복문으로 요소를 출력하는 방법은 리스트와 같다.
4) 튜플 표현식 사용하기
- 튜플을 리스트 표현식처럼 생성할 때는 다음과 같이
tuple
안에for
반복문과if
조건문을 지정한다.
- 참고로
()
(괄호) 안에 표현식을 넣으면 튜플이 아니라 제너레이터 표현식이 된다.
5) tuple
에 map
사용하기
- 튜플에
map
을 사용하는 방법도 리스트와 같다.
6) 튜플에서 가장 작은 수, 가장 큰 수, 합계 구하기
- 튜플도
min
,max
함수로 가장 작은 수와 가장 큰 수를 구하고,sum
함수로 요소의 합계를 구할 수 있다.
References
- https://dojang.io/mod/page/view.php?id=2281
- https://dojang.io/mod/page/view.php?id=2282
- https://dojang.io/mod/page/view.php?id=2283
- https://dojang.io/mod/page/view.php?id=2284
- https://dojang.io/mod/page/view.php?id=2285
- https://dojang.io/mod/page/view.php?id=2286
- https://dojang.io/mod/page/view.php?id=2287