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)
또는 변수 i
와 j
아닌 요소별로 반복 할 수 있습니다.
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] s = 0 for row in a: for elem in row: s += elem print(s)
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
번 계산되며 참조를 복사하지 않습니다.
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)]
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]
의 값을 결정하는 값 i
와 j
비교할 수 있습니다. 다음 알고리즘을 얻습니다.
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-1
에 a[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]))
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)]