1. 반복문을 사용한 2차원 리스트 출력
1.1 한 번의 반복문을 사용하기
a = [[10, 20], [30, 40], [50, 60]] for x, y in a: # 리스트의 가로 한 줄(안쪽 리스트)에서 요소 두 개를 꺼냄 print(x, y) |
10 20 30 40 50 60 |
2차원 리스트에 for를 사용하면 가로 한 줄씩 반복하게 됩니다. 전체 리스트를 기준으로 보면 안쪽 리스트가 통째로 반복됩니다. 이때 for x, y in a:와 같이 in 앞에 변수를 두 개 지정해주면 가로 한 줄(안쪽 리스트)에서 요소 두 개를 꺼내 옵니다. 당연히 in 앞에 변수의 개수는 2차원 리스트에서 가로 크기(안쪽 리스트의 요소 개수)와 일치해야 합니다. 특히 for 반복문을 한 번만 사용하는 방식은 2차원 리스트의 가로 크기가 크지 않을 때 유용합니다. |
1.2 두번의 반복문을 사용하기
a = [[10, 20], [30, 40], [50, 60]] for i in a: for j in i: print(j, end = ' ') print() |
10 20 30 40 50 60 |
먼저 for i in a:는 전체 리스트에서 가로 한 줄씩 꺼내 옵니다(안쪽 리스트를 통째로 꺼내 옴). 다시 for j in i:와 같이 가로 한 줄(안쪽 리스트) i에서 요소를 하나씩 꺼내면 됩니다. |
1.3 for 와 range 사용하기
a = [[10, 20], [30, 40], [50, 60]] for i in range(len(a)): # 세로 크기 for j in range(len(a[i])): # 가로 크기 print(a[i][j], end=' ') print() |
10 20 30 40 50 60 |
for range에 세로 크기와 가로 크기를 넣으면 인덱스로 사용할 수 있습니다. 여기서 주의할 점은 len으로 2차원 리스트 a의 크기를 구하면 리스트 안에 들어있는 모든 요소의 개수가 아니라 안쪽 리스트의 개수(세로 크기)가 나온다는 점입니다. 즉, len(a)는 6이 아니라 3입니다. 그리고 len으로 안쪽 리스트 a[i]의 크기를 구해야 안쪽 리스트에 들어있는 요소의 개수(가로 크기)가 나옵니다. 즉, len(a[i])는 2입니다. |
1.4 while 반복문
1번 | 2번 |
a = [[10, 20], [30, 40], [50, 60]] while i < len(a): # 반복할 때 리스트의 크기 활용(세로 크기) x, y = a[i] # 요소 두 개를 한꺼번에 가져오기 print(x, y) i += 1 # 인덱스를 1 증가시킴 |
a = [[10, 20], [30, 40], [50, 60]] i = 0 while i < len(a): # 세로 크기 j = 0 while j < len(a[i]): # 가로 크기 print(a[i][j], end=' ') j += 1 # 가로 인덱스를 1 증가시킴 print() i += 1 # 세로 인덱스를 1 증가시킴 |
10 20 30 40 50 60 |
|
while 반복문을 사용할 때도 리스트의 크기를 활용하면 편리합니다. 여기서도 len(a)처럼 2차원 리스트의 크기를 구했으니 안쪽 리스트의 개수(세로 크기)가 나오겠죠? 따라서 6이 아닌 3이 나옵니다. 리스트에 인덱스를 지정하여 값을 꺼내 올 때는 다음과 같이 변수 두 개를 지정해주면 가로 한 줄(안쪽 리스트)에서 요소 두 개를 한꺼번에 가져올 수 있습니다. | 먼저 while i < len(a):와 같이 세로 크기만큼 반복하면서 while j < len(a[i]):와 같이 가로 크기(안쪽 리스트의 요소 개수)만큼 반복하면 됩니다. 가로 크기는 len(a[i])와 같이 안쪽 리스트의 크기를 구하면 되겠죠? 요소에 접근할 때는 리스트[세로인덱스][가로인덱스] 형식으로 접근합니다. 따라서 세로 인덱스에 변수 i를, 가로 인덱스에 변수 j를 지정해줍니다. 요소를 가져왔으면 반드시 j += 1과 같이 가로 인덱스를 1 증가시켜 줍니다. 마찬가지로 바깥쪽 while에서는 i += 1과 같이 세로 인덱스를 1 증가시켜 줍니다. 이때 i += 1을 안쪽 while에서 수행하면 반복이 제대로 되지 않으므로 주의해야 합니다. |
2. 반복문을 사용한 2차원 리스트 입력
2.1 for 반복문으로 1차원 리스트 만들기
a = [] # 빈 리스트 for i in range(10): a.append(0) # append로 요소 추가 print(a) |
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0] |
for 반복문으로 10번 반복하면서 append로 요소를 추가하면 1차원 리스트를 만들 수 있습니다. |
2.2 for 반복문으로 1차원 리스트 만들기
b = [] # 빈 리스트 생성 for i in range(3): line = [] # 안쪽 리스트로 사용할 빈 리스트 for j in range(2): 안쪽 리스트 line.append(0) b.append(line) print(b) |
[[0, 0], [0, 0], [0, 0]] |
먼저 세로 크기만큼 반복하면서 안쪽 리스트로 사용할 빈 리스트 line을 만듭니다. 그다음에 가로 크기만큼 반복하면서 line에 append로 0을 추가합니다. 바깥쪽 반복문에서는 다시 append로 전체 리스트 a에 안쪽 리스트 line을 추가하면 됩니다. |
2.3 리스트 컴프리헨션으로 2차원 리스트 만들기
a = [[0 for j in range(2)] for i in range(3)] print(a) |
[[0, 0], [0, 0], [0, 0]] |
리스트 표현식 안에서 리스트 표현식을 사용했습니다. 먼저 [0 for j in range(2)]로 0을 2번 반복하여 [0, 0]으로 만들고 다시 for i in range(3)으로 [0, 0]을 3번 반복하여 [[0, 0], [0, 0], [0, 0]]으로 만듭니다. |
|
b = [[0] * 2 for i in range(3)] print(b) |
[[0, 0], [0, 0], [0, 0]] |
만약 for 반복문을 한 번만 사용하고 싶다면 다음과 같이 식 부분에서 리스트 자체를 곱해주면 됩니다. 즉, 0이 1개 들어있는 리스트 [0]에 2를 곱하면 [0, 0]이 되는데, 이걸 for i in range(3)으로 3번 반복해주면 [[0, 0], [0, 0], [0, 0]]이 됩니다. |
2.4 톱니형 리스트 만들기
a = [3, 1, 3, 2, 5] # 가로 크기를 저장한 리스트 b = [] # 빈 리스트 생성 for i in a: # 가로 크기를 저장한 리스트로 반복 line = [] # 안쪽 리스트로 사용할 빈 리스트 생성 for j in range(i): # 리스트 a에 저장된 가로 크기만큼 반복 line.append(0) b.append(line) # 리스트 b에 안쪽 리스트를 추가 print(b) |
[[0, 0, 0], [0], [0, 0, 0], [0, 0], [0, 0, 0, 0, 0]] |
먼저 리스트 a에 톱니형 리스트의 가로 크기를 미리 저장해 놓았습니다. 이 리스트 a를 for로 반복하면 가로 크기를 꺼내면서 5번 반복하겠죠? for 반복문 안에서 다시 for로 꺼낸 가로 크기 i만큼 반복하면서 append로 요소를 추가해줍니다. 그리고 바깥쪽 반복문에서 리스트 b에 안쪽 리스트 line을 추가하면 됩니다. | |
# 톱니형 리스트 (comprehension) a = [[0] * i for i in [3, 1, 3, 2, 5]] print(a) |
[[0, 0, 0], [0], [0, 0, 0], [0, 0], [0, 0, 0, 0, 0]] |
가로 크기가 들어있는 리스트 [3, 1, 3, 2, 5]에서 꺼낸 숫자만큼 리스트 [0]을 곱해서 톱니형 리스트를 만들었습니다. |
참고 | sorted로 2차원 리스트 정렬하기
2차원 리스트를 정렬할 때는 sorted 함수를 사용합니다.
sorted(반복가능한객체, key=정렬함수, reverse=True 또는 False)
다음은 학생 정보가 저장된 2차원 리스트를 정렬합니다.
students = [ ['john', 'C', 19], ['maria', 'A', 25], ['andrew', 'B', 7] ] print(sorted(students, key=lambda student: student[1])) # 안쪽 리스트의 인덱스 1을 기준으로 정렬 print(sorted(students, key=lambda student: student[2])) # 안쪽 리스트의 인덱스 2를 기준 |
[['maria', 'A', 25], ['andrew', 'B', 7], ['john', 'C', 19]] [['andrew', 'B', 7], ['john', 'C', 19], ['maria', 'A', 25]] |
sorted의 key에 정렬 함수를 지정하여 안쪽 리스트의 요소를 기준으로 정렬했습니다. student[1]은 안쪽 리스트의 인덱스 1을 뜻하며 'A', 'B', 'C' 순으로 정렬합니다. 마찬가지로 student[2]는 안쪽 리스트의 인덱스 2를 뜻하며 7, 19, 25 순으로 정렬합니다. 여기서는 정렬 함수를 람다 표현식으로 작성했습니다. |
3.1 리스트 할당
리스트의 할당과 복사'에서 리스트를 다른 변수에 할당해도 변수 이름만 달라질 뿐 같은 리스트(객체)라고 했습니다. 2차원 리스트도 마찬가지입니다. 다음과 같이 2차원 리스트를 만든 뒤 다른 변수에 할당하고, 요소를 변경해보면 두 리스트에 모두 반영됩니다.
a = [[10, 20], [30, 40]] b = a b[0][0] = 500 print(a) print(b) |
[[500, 20], [30, 40]] [[500, 20], [30, 40]] |
그런데 리스트 a를 copy 메서드로 b에 복사한 뒤 b의 요소를 변경해보면 리스트 a와 b에 모두 반영됩니다.
a = [[10, 20], [30, 40]] b = a.copy() b[0][0] = 500 print(a) print(b) |
[[500, 20], [30, 40]] [[500, 20], [30, 40]] |
2차원 이상의 다차원 리스트는 리스트를 완전히 복사하려면 copy 메서드 대신 copy 모듈의 deepcopy 함수를 사용해야 합니다.
a = [[10, 20], [30, 40]] import copy # copy 모듈을 가져옴 b = copy.deepcopy(a) # copy.deepcopy 함수를 사용하여 깊은 복사 b[0][0] = 500 print(a) print(b) |
[[10, 20], [30, 40]] [[500, 20], [30, 40]] |
이제 리스트 b의 요소를 변경해도 리스트 a에는 영향을 미치지 않습니다. copy.deepcopy 함수는 중첩된 리스트(튜플)에 들어있는 모든 리스트(튜플)를 복사하는 깊은 복사(deep copy)를 해줍니다. 2차원 리스트는 세로, 가로 순으로 접근한다는 점만 기억하면 됩니다.
'Programming > Python' 카테고리의 다른 글
[코딩도장-파이썬] 문자열 응용하기 2 (formatting, 포매팅) (0) | 2020.11.24 |
---|---|
[코딩도장-파이썬] 문자열 응용하기 1 (0) | 2020.11.23 |
[코딩도장-파이썬] 2차원 리스트 사용하기 1 (0) | 2020.11.20 |
[코딩도장-파이썬] 리스트(List)와 튜플(Tuple) 응용하기 3 (0) | 2020.11.19 |
[코딩도장-파이썬] 리스트(List)와 튜플(Tuple) 응용하기 2 (0) | 2020.11.19 |