13. 2차원 리스트
1. 키워드
- 2차원 리스트(튜플)
2. 2차원 리스트 사용하기
- 2차원 리스트는 다음과 같이 행과 열 형태로 이루어져 있으며 행과 열 모두 0부터 시작한다.
3. 2차원 리스트를 만들고 요소에 접근하기
- 2차원 리스트는 리스트 안에 리스트를 넣어서 만들 수 있으며 안쪽의 각 리스트는
,
(콤마)로 구분한다.
- 숫자 2개씩 3묶음으로 리스트를 만들어보자.
- 리스트를 한 줄로 입력했지만 가로, 세로를 알아보기 쉽게 세 줄로 입력해도 된다.
1) 2차원 리스트의 요소에 접근하기
- 2차원 리스트의 요소에 접근하거나 값을 할당할 때는 리스트 뒤에
[]
(대괄호)를 두 번 사용하며[]
안에 세로 인덱스와 가로 인덱스를 지정해 주면 된다.
>>> a = [[10, 20], [30, 40], [50, 60]]
>>> a[0][0]
10
>>> a[1][1]
40
>>> a[2][1]
60
>>> a[0][1] = 1000
>>> a[0][1]
1000
톱니형 리스트
- 2차원 리스트
[[10, 20], [30, 40], [50, 60]]
은 가로 크기가 일정한 사각형 리스트이다. - 특히 파이썬에서는 가로 크기가 불규칙한 톱니형 리스트(Jagged List)도 만들 수 있다.
- 톱니형 리스트는 다음과 같이
append
메서드 등을 사용하여 동적으로 생성할 수도 있다.
2차원 튜플
- 다음과 같이 튜플 안에 튜플을 넣는 방식, 튜플 안에 리스트를 넣는 방식, 리스트 안에 튜플을 넣는 방식 등이 가능하다.
a = ((10, 20), (30, 40), (50, 60))
b = ([10, 20], [30, 40], [50, 60])
c = [(10, 20), (30, 40), (50, 60)]
- 튜플은 내용을 변경할 수 없으므로
a
는 안쪽과 바깥쪽 모두 요소를 변경할 수 없다. b
는 안쪽 리스트만 요소를 변경할 수 있고,c
는 바깥쪽 리스트만 요소를 변경할 수 있다.
사람이 알아보기 쉽게 출력하기
- 2차원 리스트를 출력하면 한 줄로 쭉 붙어서 출력된다.
- 만약 2차원 리스트의 사각형 구조를 유지하도록 출력하려면
pprint
모듈의pprint
함수를 사용한다.
indent
는 들여쓰기 칸 수,width
는 가로 폭이다.
4. 반복문으로 2차원 리스트의 요소를 모두 출력하기
- 반복문을 사용하여 2차원 리스트의 요소를 모두 출력하는 방법을 알아보자.
1) for
반복문을 한 번만 사용하기
- 먼저
for
반복문을 한 번만 사용하는 방식이다.
- 2차원 리스트에
for
를 사용하면 가로 한 줄씩 반복하게 된다. - 전체 리스트를 기준으로 보면 안쪽 리스트가 통째로 반복된다.
- 이때
for x, y in a:
와 같이in
앞에 변수를 두 개 지정해 주면 가로 한 줄(안쪽 리스트)에서 요소 두 개를 꺼낸다.
- 당연히
in
앞에 변수의 개수는 2차원 리스트에서 가로 크기(안쪽 리스트의 요소 개수)와 일치해야 한다. - 특히
for
반복문을 한 번만 사용하는 방식은 2차원 리스트의 가로 크기가 크지 않을 때 유용하다.
2) for
반복문을 두 번 사용하기
- 이번에는
for
반복문을 두 번 사용해서 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
에서 요소를 하나씩 꺼내면 된다.
3) for
와 range
사용하기
- 이번에는
for
와range
에 세로 크기와 가로 크기를 지정해서 2차원 리스트의 요소를 인덱스로 접근해 보자.
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
이다.
for i in range(len(a)):
는 세로 크기3
만큼 반복하고,for j in range(len(a[i])):
는 가로 크기2
만큼 반복한다.- 요소에 접근할 때는
리스트[세로인덱스][가로인덱스]
형식으로 접근한다.
- 따라서 세로 인덱스에 변수
i
를, 가로 인덱스에 변수j
를 지정해 준다.
4) while
반복문을 한 번 사용하기
- 이번에는
while
반복문을 사용하여 2차원 리스트의 요소를 출력해 보자.
a = [[10, 20], [30, 40], [50, 60]]
i = 0
while i < len(a):
x, y = a[i]
print(x, y)
i += 1
# 10 20
# 30 40
# 50 60
while
반복문을 사용할 때도 리스트의 크기를 활용하면 편리하다.- 여기서도
len(a)
처럼 2차원 리스트의 크기를 구했으니 안쪽 리스트의 개수(세로 크기)가 나온다. - 따라서
6
이 아닌3
이 나온다.
- 리스트에 인덱스를 지정하여 값을 꺼내 올 때는 다음과 같이 변수 두 개를 지정해 주면 가로 한 줄(안쪽 리스트)에서 요소 두 개를 한꺼먼에 가져올 수 있다.
- 요소를 가져왔으면 반드시
i += 1
과 같이 인덱스를1
증가시켜 준다.
5) while
반복문을 두 번 사용하기
while
반복문을 두 번 사용해 보자.
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
print()
i += 1
# 10 20
# 30 40
# 50 60
- 먼저
while i < len(a):
와 같이 세로 크기만큼 반복하면서while j < len(a[i]):
와 같이 가로 크기(안쪽 리스트의 요소 개수)만큼 반복하면 된다.
- 요소에 접근할 때는
리스트[세로인덱스][가로인덱스]
형식으로 접근한다.
- 따라서 새로 인덱스에 변수
i
를, 가로 인덱스에 변수j
를 지정해 준다.
- 요소를 가져왔으면 반드시
j += 1
과 같이 가로 인덱스를1
증가시켜 준다. - 마찬가지로 바깥쪽 while에서는
i += 1
과 같이 세로 인덱스를1
증가시켜 준다.
5. 반복문으로 리스트 만들기
- 이번에는
for
반복문과append
를 활용하여 리스트를 만드는 방법을 알아보자.
1) for 반복문으로 1차원 리스트 만들기
- 먼저 요소 10개가 일렬로 늘어서 있는 1차원 리스트부터 만들어보자.
2) for 반복문으로 2차원 리스트 만들기
- 이번에는
for
반복문을 사용하여 2차원 리스트를 만들어보자.
a = []
for i in range(3):
line = []
for j in range(2):
line.append(0)
a.append(line)
print(a)
# [[0, 0], [0, 0], [0, 0]]
- 먼저 세로 크기만큼 반복하면서 안쪽 리스트로 사용할 빈 리스트
line
을 만든다.
- 그다음에 가로 크기만큼 반복하면서
line
에append
로0
을 추가한다. - 바깥쪽 반복문에서는 다시
append
로 전체 리스트a
에 안쪽 리스트line
을 추가하면 된다.
- 여기서는
append
에 리스트를 넣으면 리스트 안에 리스트가 들어가는 특성을 이용했다.
3) 리스트 표현식으로 2차원 리스트 만들기
- 리스트 표현식을 활용하면 코드 한 줄로 2차원 리스트를 만들 수 있다.
- 리스트 표현식 안에서 리스트 표현식을 사용했다.
- 만약 for 반복문을 한 번만 사용하고 싶다면 다음과 같이 식 부분에서 리스트 자체를 곱해주면 된다.
4) 톱니형 리스트 만들기
- 가로 크기를 알고 있다고 가정하고, 톱니형 리스트를 만들어보자.
a = [3, 1, 3, 2, 5]
b = []
for i in a:
line = []
for j in range(i):
line.append(0)
b.append(line)
print(b)
# [[0, 0, 0], [0], [0, 0, 0], [0, 0], [0, 0, 0, 0, 0]]
- 리스트 표현식을 활용하면 간단하게 만들 수 있다.
>>> a = [[0] * i for i in [3, 1, 3, 2, 5]]
>>> a
[[0, 0, 0], [0], [0, 0, 0], [0, 0], [0, 0, 0, 0, 0]]
sorted
로 2차원 리스트 정렬하기
- 2차원 리스트를 정렬할 때는
sorted
함수를 사용한다.
- 다음은 학생 정보가 저장된 2차원 리스트를 정렬한다.
students = [["john", "C", 19],
["maria", "A", 25],
["andrew", "B", 7]]
print(sorted(students, key=lambda student: student[1]))
print(sorted(students, key=lambda student: student[2]))
# [['maria', 'A', 25], ['andrew', 'B', 7], ['john', 'C', 19]]
# [['andrew', 'B', 7], ['john', 'C', 19], ['maria', 'A', 25]]
6. 2차원 리스트의 할당과 복사 알아보기
- 다음과 같이 2차원 리스트를 만든 뒤 다른 변수에 할당하고, 요소를 변경해 보면 두 리스트에 모두 반영된다.
>>> a = [[10, 20], [30, 40]]
>>> b = a
>>> b[0][0] = 500
>>> a
[[500, 20], [30, 40]]
>>> b
[[500, 20], [30, 40]]
- 그런데 리스트
a
를copy
메서드로b
에 복사한 뒤b
의 요소를 변경해 보면 리스트a
와b
에 모두 반영된다.
>>> a = [[10, 20], [30, 40]]
>>> b = a.copy()
>>> b[0][0] = 500
>>> a
[[500, 20], [30, 40]]
>>> b
[[500, 20], [30, 40]]
- 2차원 이상의 다차원 리스트를 완전히 복사하려면
copy
메서드 대신copy
모듈의deepcopy
함수를 사용해야 한다.
>>> import copy
>>> a = [[10, 20], [30, 40]]
>>> b = copy.deepcopy(a)
>>> b[0][0] = 500
>>> a
[[10, 20], [30, 40]]
>>> b
[[500, 20], [30, 40]]
- 이제 리스트
b
의 요소를 변경해도 리스트a
에는 영향을 미치지 않는다. copy.deepcopy
함수는 중첩된 리스트(튜플)에 들어있는 모든 리스트(튜플)를 복사하는 깊은 복사를 해준다.