[python] list - 2중, 3중 리스트 생성
일단 2중, 3중 리스트 생성 시 기억해야 할 점은
1. 리스트는 for _ in range() 구문과 * 구문의 적절한 조합으로 생성 가능하다는 것,
- * 사용 시 자동으로 1회 unpacking이 이루어 진다는 것
- for _ in range() 사용 시 자동 unpacking은 없으나, 타입이 generator 객체이므로 list로 형변환 할 것
2. for _ in range() 구문에서 순서 주의할 것 (column -> row 순서 )
이 두 가지이다.
경우에 따라 나눠, 자세히 알아보자.
1. 2중 리스트 생성
[1] 목표 설정
예를 들어 다음과 같은 row = 3, column = 2인 2중 리스트를 생성한다고 가정하자.
즉, [[0, 0], [0, 0], [0, 0]]인 리스트를 생성하자.
[2] 코드 작성
# 목표
# [[0, 0], [1, 1], [2, 2]]
해당 목표를 달성하기 위한 코드는 여러 가지가 있다.
(1) * 구문 (O)
# (1)
print([[0] * 2] * 3)
# 결과: [[0, 0], [0, 0], [0, 0]]
- [0, 0] : 가장 안쪽의 리스트를 (column 수만큼을 크기=원소개수=len 로 갖는) 생성하고 ([0] * 2 결과)
- [0, 0], [0, 0], [0, 0] : *3을 함으로써 row를 생성한다 ([[0, 0]] * 3 결과)
** 주의: [[0, 0]] * 3 이 아니라, [0, 0] * 3 사용 시 [0, 0, 0, 0, 0, 0] 출력
** 즉, * 사용 시에는 한 번 더 []로 감싸야 함
(2) * 구문과 for _ in range() 구문 (O)
# (2)
print([[0] * 2 for _ in range(3)])
# 결과: [[0, 0], [0, 0], [0, 0]]
# 참고: type([0] * 2 for _ in range(3)) -> <class 'generator'>
- [0, 0]: 가장 안쪽의 리스트를 (column 수만큼을 크기=원소개수=len 로 갖는) 생성하고([0] * 2 결과)
- [0, 0], [0, 0], [0, 0] : for _ in range(3) 문을 통해 [0] * 2를 3번 반복한다는 의미이다.
이때, for _ in range(3)문의 return값은 generator이다.
원소를 확인하면 [0, 0]이 각 원소인 것을 확인할 수 있다.
generator = ([0] * 2 for _ in range(3))
for item in generator:
print(item)
# 결과: [[0, 0], [0, 0], [0, 0]]
for _ in range(3) 구문의 결과 (generator)를 리스트로 변환하여 -> 원하는 배열 [[0, 0], [0, 0], [0, 0]]을 얻을 수 있다.
([for구문] 을 통해 리스트로 변환)
(3) * 구문과 for _ in range() 구문 (X)
# (3)
print([[0] for _ in range(2)] * 3)
# 결과: [[0], [0], [0], [0], [0], [0]]
(2) 경우와 for문, *의 순서만 바뀌었다.
이때 [0]이 하나씩만 만들어진다.
- generator 객체: [0] for _ in range(2)의 결과
- [[0], [0]] : [[0] for _ in range(2)]의 결과
- [0], [0] : [[0], [0]]을 1번 언패킹한 결과 ([[0], [0]] * 3의 중간과정)
- [[0], [0], [0], [0], [0], [0]]: [[0], [0]] * 3의 결과
[3] 결론
[0] -> [0, 0]으로 만들기 위해서는 *를 이용해야 한다. (for문 사용 안됨 !)
[0] -> [0], [0]으로 만들기 위해서는 * 또는 for _ in range() 구문을 이용한다.
- * 사용 시, 한 번 더 []로 감싸야 한다 (unpacking 자동으로 1번 이루어짐)
- for _ in range() 사용 시, unpacking이 자동으로 이루어지지 않는다. (단, 결과가 generator 객체이므로 list 형변환 필요)
2. 3중 리스트 생성
[1] 목표 설정
예를 들어 다음과 같은 높이=2, 세로=2, 가로=3인 2중 리스트를 생성한다고 가정하자.
즉, [ [[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]] ] 인 리스트를 생성하자.
[2] 코드 작성
# 목표
# [[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]
해당 목표를 달성하기 위한 코드는 여러 가지가 있다.
# (1)
print([[[0] * 3 for _ in range(2)] for _ in range(2)])
# 결과: [[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]
- [0, 0, 0] : [0] * 3의 결과
- [[0, 0, 0], [0, 0, 0], [0, 0, 0]] : [[0] * 3 for _ in range(2)]의 결과
- [[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]: [[0] * 3 for _ in range(2)] for _ in range(2)의 결과
** 즉, * 사용 시에는 한 번 더 []로 감싸야 함
# (1)
print([[[0] *3 for _ in range(2)] for _ in range(2)])
# 결과: [[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]
# (2)
print([[[0] *3] * 2 for _ in range(2)])
# 결과: [[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]
# (3)
print([[[0] *3] * 2] * 2)
# 결과: [[[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]]
아래 모두 다 가능 !
- [[[[0] * 가로] for _ in range(세로)] * 높이
- [[[[0] * 가로] for _ in range(세로)] for _ in range(높이)] # (1)
- [[[[0] * 가로] * 세로 for _ in range(높이)] # (2)
- [[[[0] * 가로] * 세로] * 높이 # (3)
[3] 결론 (2중 리스트 결론과 동일)
[0] -> [0, 0]으로 만들기 위해서는 *를 이용해야 한다. (for문 사용 안됨 !)
[0] -> [0], [0]으로 만들기 위해서는 * 또는 for _ in range() 구문을 이용한다.
- * 사용 시, 한 번 더 []로 감싸야 한다 (unpacking 자동으로 1번 이루어짐)
- for _ in range() 사용 시, unpacking이 자동으로 이루어지지 않는다. (단, 결과가 generator 객체이므로 list 형변환 필요)