Two-dimensional lists (arrays) - Learn Python 3 - Snakify

Lesson 9
2 차원 목록 (배열)


1. 중첩 목록 : 처리 및 인쇄

실제 상황에서는 종종 직사각형 데이터 테이블을 저장해야합니다. [이것에 대해 더 많이 말하십시오!] 이러한 테이블을 행렬 또는 2 차원 배열이라고합니다. 파이썬에서 어떤 테이블이라도리스트 (리스트, 각 요소는 차례로리스트)의리스트로 나타낼 수 있습니다. 예를 들어, 2 행 3 열의 수치 표를 작성한 후 다음과 같이 조작하는 프로그램이 있습니다.
a = [[1, 2, 3], [4, 5, 6]]
print(a[0])
print(a[1])
b = a[0]
print(b)
print(a[0][2])
a[0][1] = 7
print(a)
print(b)
b[2] = 9
print(a[0])
print(b)

여기서 a 의 첫 번째 요소 인 a[0] 은 숫자 목록 [1, 2, 3] 입니다. 새 목록의 첫 번째 요소 a[0][0] == 1 . 또한 a[0][1] == 2 , a[0][2] == 3 , a[1][0] == 4 , a[1][1] == 5 , a[1][2] == 6 .

2 차원 배열을 처리하려면 대개 중첩 루프를 사용합니다. 첫 번째 루프는 행 번호를 반복하고 두 번째 루프는 행 내부의 요소를 통과합니다. 예를 들어, 숫자를 공백으로 구분하여 라인별로 2 차원 숫자 목록을 화면에 표시하는 방법입니다.

a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]]
for i in range(len(a)):
    for j in range(len(a[i])):
        print(a[i][j], end=' ')
    print()

우리는 이미 파이썬에서 for-loop 변수가 range() 뿐만 아니라 일반적으로 모든 시퀀스 요소를 반복 할 수 있음을 설명하려고했습니다. 파이썬의 시퀀스는리스트와 문자열 (그리고 우리가 아직 만난 적이없는 다른 객체)입니다. 당신은 루프의 편리한 기능을 사용하여 2 차원 배열을 인쇄 할 수있는 방법을 봐 for :

a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]]
for row in a:
    for elem in row:
        print(elem, end=' ')
    print()

당연히, 한 줄을 출력하려면 join() 메소드를 사용할 수 있습니다 :

for row in a:
    print(' '.join([str(elem) for elem in row]))

두 개의 중첩 된 루프를 사용하여 2 차원 목록의 모든 숫자의 합을 계산하는 방법은 다음과 같습니다.

a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]]
s = 0
for i in range(len(a)):
    for j in range(len(a[i])):
        s += a[i][j]
print(s)

또는 변수 ij 아닌 요소별로 반복 할 수 있습니다.

a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]]
s = 0
for row in a:
    for elem in row:
        s += elem
print(s)
Advertising by Google, may be based on your interests

2. 중첩 목록 : 만들기

n 의 행 수와 m 의 열 수라는 두 개의 숫자가 있다고 가정하십시오. n x m 크기의 목록을 만들어야합니다. 예를 들어, 0으로 채워야합니다.

분명한 해결책은 잘못되었습니다.

a = [[0] * m] * n

이것은 a[0][0] 의 값을 5 로 설정하고 a[1][0] 의 값을 인쇄하면 쉽게 볼 수 있습니다 - 또한 5와 같습니다. 이유는 [0] * m 은 목록이 아닌 m 0 목록에 대한 참조 만 반환합니다. 이 요소를 다음에 반복하면 동일한 목록을 모두 참조하는 n 항목 목록이 만들어집니다 (목록에 대한 작업 b = a 는 새 목록을 만들지 않음) 결과 목록의 모든 행은 실제로 동일합니다 끈.

비주얼 라이저를 사용하여 목록의 ID를 추적하십시오. 두 개의 목록이 동일한 ID 번호를 가지고 있다면 실제로 메모리에있는 동일한 목록입니다.

n = 3
m = 4
a = [[0] * m] * n
a[0][0] = 5
print(a[1][0])

따라서 2 차원 목록은 단순히 문자열을 반복하여 만들 수 없습니다. 무엇을해야합니까? ..

가능한 방법 : n 요소 (예 : n 0) 목록을 만든 다음 각 요소를 m 개의 요소로 구성된 다른 1 차원 목록에 대한 링크로 만들 수 있습니다.

n = 3
m = 4
a = [0] * n
for i in range(n):
    a[i] = [0] * m

또 다른 (그러나 비슷한) 방법 : 빈 목록을 만든 다음 n 번에 새 요소를 append 합니다 (이 요소는 길이가 m 목록이어야 함).

n = 3
m = 4
a = []
for i in range(n):
    a.append([0] * m)

하지만 가장 쉬운 방법은 생성기를 사용하여 n 요소 목록을 만드는 것입니다. 각 요소는 m 0 목록입니다.

n = 3
m = 4
a = [[0] * m for i in range(n)]

이 경우 각 요소는 다른 요소와 독립적으로 생성됩니다. list [0] * m 은 새로운 것으로 n 번 계산되며 참조를 복사하지 않습니다.

Advertising by Google, may be based on your interests

3. 어떻게 2 차원 배열을 입력합니까?

예를 들어, 프로그램은 n 행의 형태로 입력 된 2 차원 배열을 취합니다. 각 행은 공백으로 구분 된 m 숫자를 포함합니다. 프로그램이 어떻게 그것을 읽도록 강요합니까? 할 수있는 방법의 예 :

# 입력의 첫 번째 줄은 배열의 행 수입니다.
n = int(input()) 
a = []
for i in range(n):
    a.append([int(j) for j in input().split()])

또는 정교한 중첩 호출을 사용하지 않아도됩니다.

# 입력의 첫 번째 줄은 배열의 행 수입니다.
n = int(input()) 
a = []
for i in range(n):
    row = input().split()
    for i in range(len(row)):
        row[i] = int(row[i])
    a.append(row)

발전기로도 똑같이 할 수 있습니다.

# 입력의 첫 번째 줄은 배열의 행 수입니다.
n = int(input()) 
a = [[int(j) for j in input().split()] for i in range(n)]
Advertising by Google, may be based on your interests

4. 2 차원 배열 처리 : 예제

정사각형 배열 ( n 행과 n 열로 구성된 배열)이 있다고 가정합니다. 그리고 주 대각선의 요소를 1 (즉, i==j 인 해당 요소 a[i][j] )로 설정하고 대각선보다 위의 요소를 0으로 설정하고 요소를 설정해야한다고 가정합니다 그 대각선이 2와 같습니다. 즉, 당신은 그러한 배열을 생성해야합니다 ( n==4 예제) :

 
1 0 0 0
2 1 0 0
2 2 1 0
2 2 2 1
(이 경우 a[0][0] = 1 , a[0][1] = 0 등을 설정하여 수동으로 수행 할 수 있지만 100 행 100 열의 배열에 대해서는 수동으로 수행하지 않습니다 이는 종종 그렇습니다.)

우리는이 문제를 해결할 수있는 몇 가지 방법을 보여 드리고자합니다. 첫째, 주요 대각선 위에있는 요소 a[i][j] i<j 인 요소 a[i][j] 이고 주 대각선 i>j 아래 요소의 요소입니다. 따라서 a[i][j] 의 값을 결정하는 값 ij 비교할 수 있습니다. 다음 알고리즘을 얻습니다.

n = 4
a = [[0] * n for i in range(n)]
for i in range(n):
    for j in range(n):
        if i < j:
            a[i][j] = 0
        elif i > j:
            a[i][j] = 2
        else:
            a[i][j] = 1
for row in a:
    print(' '.join([str(elem) for elem in row]))

이 알고리즘은 느립니다 : 두 개의 루프를 사용하고 각 쌍 (i,j) if 명령어 하나 또는 두 개를 실행합니다. 알고리즘을 복잡하게 만들면 조건문없이 알고리즘을 수행 할 수 있습니다.

첫째, 주요 대각선을 채우십시오.이 루프는 하나의 루프가 필요합니다.

for i in range(n):
    a[i][i] = 1

그런 다음 주 대각선 위의 모든 요소를 ​​0으로 채 웁니다. 이것을 만들기 위해서 숫자 i 를 가진 각 행에 대해 j = i+1 , ..., n-1a[i][j] 에 값을 할당해야합니다. 이렇게하려면 중첩 루프가 필요합니다.

for i in range(n):
    for j in range(i + 1, n):
        a[i][j] = 0

유추하여, j = 0 , ..., i-1 대해 요소 a[i][j]2 동일하게 설정합니다.

for i in range(n):
    for j in range(0, i):
        a[i][j] = 2

이 모든 코드를 결합하여 다른 솔루션을받을 수 있습니다.

n = 4
a = [[0] * n for i in range(n)]
for i in range(n):
    for j in range(0, i):
        a[i][j] = 2
    a[i][i] = 1
    for j in range(i + 1, n):
        a[i][j] = 0
for row in a:
    print(' '.join([str(elem) for elem in row]))

목록의 다음 행을 만들기 위해 목록을 반복하는 또 다른 해결책이 있습니다. 목록의 i 번째 줄은 i 숫자 2 , 하나의 정수 1 , ni-1 제로 다음으로 구성됩니다.

n = 4
a = [0] * n
for i in range(n):
    a[i] = [2] * i + [1] + [0] * (n - i - 1)
for row in a:
    print(' '.join([str(elem) for elem in row]))    

평소와 같이 루프를 생성기로 바꿀 수 있습니다.

n = 4
a = [0] * n
a = [[2] * i + [1] + [0] * (n - i - 1) for i in range(n)]
for row in a:
    print(' '.join([str(elem) for elem in row]))    
Advertising by Google, may be based on your interests

5. 2 차원 배열 : 중첩 된 생성자

중첩 된 생성자를 사용하여 2 차원 배열을 만들고 문자열의 목록 생성자를 모든 문자열의 생성자 안에 배치 할 수 있습니다. 생성자를 사용하여 n 행과 m 열의 목록을 만들 수 있습니다 (각 요소는 m 0 목록 인 n 요소의 목록을 만듭니다).

[[0] * m for i in range(n)]

그러나 내부 목록은 또한 예를 들어 그러한 생성자를 사용하여 생성 될 수 있습니다. [0 for j in range(m)] . 발전기를 다른 발전기에 중첩하면

[[0 for j in range(m)] for i in range(n)]

그것은 우리의 문제와 어떤 관련이 있습니까? 문제는 숫자 0이 i (줄 번호)와 j (열 번호)에 의존하는 식으로 바뀌면 몇 가지 수식에 따라 채워진 행렬을 얻게된다는 것입니다.

예를 들어, 다음 배열을 초기화해야한다고 가정합니다 (편의상 항목 사이에 여분의 공백이 추가됩니다).

0  0  0  0  0  0
0  1  2  3  4  5
0  2  4  6  8 10
0  3  6  9 12 15
0  4  8 12 16 20

이 배열에는 n = 5 행, m = 6 열이 있고 행 색인 i 및 열 색인 j 갖는 요소는 공식 a[i][j] = i * j 의해 계산됩니다.

늘 그렇듯이 생성기를 사용하여 그러한 배열을 만들 수 있습니다.

[[i * j for j in range(m)] for i in range(n)]
Advertising by Google, may be based on your interests