Skip to content

13. 2차원 리스트


1. 키워드

  • 2차원 리스트(튜플)


2. 2차원 리스트 사용하기

  • 2차원 리스트는 다음과 같이 행과 열 형태로 이루어져 있으며 행과 열 모두 0부터 시작한다.


001


3. 2차원 리스트를 만들고 요소에 접근하기

  • 2차원 리스트는 리스트 안에 리스트를 넣어서 만들 수 있으며 안쪽의 각 리스트는 ,(콤마)로 구분한다.


리스트 = [[, ], [, ], [, ]]


  • 숫자 2개씩 3묶음으로 리스트를 만들어보자.


>>> a = [[10, 20], [30, 40], [50, 60]]

>>> a
[[10, 20], [30, 40], [50, 60]]


  • 리스트를 한 줄로 입력했지만 가로, 세로를 알아보기 쉽게 세 줄로 입력해도 된다.


a = [[10, 20],
     [30, 40],
     [50, 60]]


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)도 만들 수 있다.


a = [[10, 20],
     [500, 600, 700],
     [9],
     [30, 40],
     [8],
     [800, 900, 1000]]


  • 톱니형 리스트는 다음과 같이 append 메서드 등을 사용하여 동적으로 생성할 수도 있다.


>>> a = []

>>> a.append([])
>>> a[0].append(10)
>>> a[0].append(20)

>>> a.append([])
>>> a[1].append(500)
>>> a[1].append(600)
>>> a[1].append(700)

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


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차원 리스트를 출력하면 한 줄로 쭉 붙어서 출력된다.


>>> a = [[10, 20], [30, 40], [50, 60]]

>>> a
[[10, 20], [30, 40], [50, 60]]


  • 만약 2차원 리스트의 사각형 구조를 유지하도록 출력하려면 pprint 모듈의 pprint 함수를 사용한다.


>>> from pprint import pprint

>>> pprint(a, indent=4, width=20)
[   [10, 20],
    [30, 40],
    [50, 60]]


  • indent는 들여쓰기 칸 수, width는 가로 폭이다.


4. 반복문으로 2차원 리스트의 요소를 모두 출력하기

  • 반복문을 사용하여 2차원 리스트의 요소를 모두 출력하는 방법을 알아보자.


1) for 반복문을 한 번만 사용하기

  • 먼저 for 반복문을 한 번만 사용하는 방식이다.


>>> 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 앞에 변수를 두 개 지정해 주면 가로 한 줄(안쪽 리스트)에서 요소 두 개를 꺼낸다.


002


  • 당연히 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에서 요소를 하나씩 꺼내면 된다.


003


3) forrange 사용하기

  • 이번에는 forrange에 세로 크기와 가로 크기를 지정해서 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


  • forrange에 세로 크기와 가로 크기를 넣으면 인덱스로 사용할 수 있다.
  • 여기서 주의할 점은 len으로 2차원 리스트 a의 크기를 구하면 리스트 안에 들어있는 모든 요소의 개수가 아니라 안쪽 리스트의 개수(세로 크기)가 나온다는 점이다.
  • 즉, len(a)6이 아니라 3이다.
  • 그리고 len으로 안쪽 리스트 a[i]의 크기를 구해야 안쪽 리스트에 들어있는 요소의 개수(가로 크기)가 나온다.
  • 즉, len(a[i])2이다.


for i in range(len(a)):
    for j in range(len(a[i])):


  • for i in range(len(a)):는 세로 크기 3만큼 반복하고, for j in range(len(a[i])):는 가로 크기 2만큼 반복한다.
  • 요소에 접근할 때는 리스트[세로인덱스][가로인덱스] 형식으로 접근한다.


  • 따라서 세로 인덱스에 변수 i를, 가로 인덱스에 변수 j를 지정해 준다.


print(a[i][j], end=" ")


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 = 0

while i < len(a):


  • 리스트에 인덱스를 지정하여 값을 꺼내 올 때는 다음과 같이 변수 두 개를 지정해 주면 가로 한 줄(안쪽 리스트)에서 요소 두 개를 한꺼먼에 가져올 수 있다.


x, y = a[i]


  • 요소를 가져왔으면 반드시 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 = 0

while i < len(a):
    j = 0

    while j < len(a[i]):


  • 요소에 접근할 때는 리스트[세로인덱스][가로인덱스] 형식으로 접근한다.


  • 따라서 새로 인덱스에 변수 i를, 가로 인덱스에 변수 j를 지정해 준다.


print(a[i][j], end=" ")


  • 요소를 가져왔으면 반드시 j += 1과 같이 가로 인덱스를 1 증가시켜 준다.
  • 마찬가지로 바깥쪽 while에서는 i += 1과 같이 세로 인덱스를 1 증가시켜 준다.


5. 반복문으로 리스트 만들기

  • 이번에는 for 반복문과 append를 활용하여 리스트를 만드는 방법을 알아보자.


1) for 반복문으로 1차원 리스트 만들기

  • 먼저 요소 10개가 일렬로 늘어서 있는 1차원 리스트부터 만들어보자.


a = []

for i in range(10):
    a.append(0)

print(a)

# [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]


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을 만든다.


for i in range(3):
    line = []


  • 그다음에 가로 크기만큼 반복하면서 lineappend0을 추가한다.
  • 바깥쪽 반복문에서는 다시 append로 전체 리스트 a에 안쪽 리스트 line을 추가하면 된다.


    for j in range(2):
        line.append(0)

    a.append(line)


  • 여기서는 append에 리스트를 넣으면 리스트 안에 리스트가 들어가는 특성을 이용했다.


3) 리스트 표현식으로 2차원 리스트 만들기

  • 리스트 표현식을 활용하면 코드 한 줄로 2차원 리스트를 만들 수 있다.


>>> a = [[0 for j in range(2)] for i in range(3)]

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


  • 리스트 표현식 안에서 리스트 표현식을 사용했다.


  • 만약 for 반복문을 한 번만 사용하고 싶다면 다음과 같이 식 부분에서 리스트 자체를 곱해주면 된다.


>>> a = [[0] * 2 for i in range(3)]

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


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 함수를 사용한다.


sorted(반복가능한객체, key=정렬함수, reverse=True 또는 False)


  • 다음은 학생 정보가 저장된 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]]


  • 그런데 리스트 acopy 메서드로 b에 복사한 뒤 b의 요소를 변경해 보면 리스트 ab에 모두 반영된다.


>>> 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 함수는 중첩된 리스트(튜플)에 들어있는 모든 리스트(튜플)를 복사하는 깊은 복사를 해준다.

References