Lesson 9
Zweidimensionale Listen (Arrays)
1. Geschachtelte Listen: Verarbeiten und Drucken
In der Praxis Oft müssen Aufgaben eine rechteckige Datentabelle speichern. [Sag mehr dazu!] Solche Tabellen heißen Matrizen oder zweidimensionale Arrays. In Python kann jede Tabelle als Liste von Listen dargestellt werden (eine Liste, in der jedes Element wiederum eine Liste ist). Zum Beispiel ist hier das Programm, das eine numerische Tabelle mit zwei Zeilen und drei Spalten erstellt und dann einige Manipulationen damit ausführt: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)
Das erste Element a
hier - a[0]
- ist eine Liste von Zahlen [1, 2, 3]
. Das erste Element dieser neuen Liste ist a[0][0] == 1
; außerdem ist a[0][1] == 2
, a[0][2] == 3
, a[1][0] == 4
, a[1][1] == 5
, a[1][2] == 6
.
Um 2-dimensionale Arrays zu verarbeiten, verwenden Sie normalerweise verschachtelte Schleifen. Die erste Schleife durchläuft die Zeilennummer, die zweite Schleife durchläuft die Elemente innerhalb einer Zeile. So zeigen Sie z. B. auf dem Bildschirm zeilenweise eine zweidimensionale numerische Liste an und trennen die Zahlen mit Leerzeichen:
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()
Wir haben bereits versucht zu erklären, dass eine For-Loop-Variable in Python nicht nur über einen range()
, sondern generell über alle Elemente einer Sequenz iterieren kann. Sequenzen in Python sind Listen und Strings (und einige andere Objekte, die wir noch nicht erreicht haben). Schauen Sie, wie Sie ein zweidimensionales Array mit dieser praktischen Loop-Funktion drucken können for
:
a = [[1, 2, 3, 4], [5, 6], [7, 8, 9]] for row in a: for elem in row: print(elem, end=' ') print()
Um eine einzelne Zeile auszugeben, können Sie natürlich method join()
:
for row in a: print(' '.join([str(elem) for elem in row]))
So können Sie mit 2 verschachtelten Schleifen die Summe aller Zahlen in der 2-dimensionalen Liste berechnen:
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)
Oder das Gleiche mit der Iteration durch Elemente, nicht mit den Variablen i
und 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. Geschachtelte Listen: Erstellen
Angenommen, zwei Zahlen sind gegeben: die Anzahl der Zeilen von n
und die Anzahl der Spalten m
. Sie müssen eine Liste der Größe n
× m
erstellen, die z. B. mit Nullen gefüllt ist.
Die offensichtliche Lösung scheint falsch zu sein:
a = [[0] * m] * n
Das kann man leicht sehen, wenn man den Wert von a[0][0]
auf 5
setzt und dann den Wert von a[1][0]
- es ist auch gleich 5. Der Grund ist, [0] * m
gibt nur einen Verweis auf eine Liste von m
Nullen zurück, aber keine Liste. Das anschließende Wiederholen dieses Elements erstellt eine Liste von n
Elementen, die alle auf dieselbe Liste verweisen (genauso wie die Operation b = a
für Listen die neue Liste nicht erstellt), sodass alle Zeilen in der resultierenden Liste tatsächlich gleich sind Zeichenfolge.
Mit unserem Visualizer behalten Sie die ID von Listen im Auge. Wenn zwei Listen die gleiche ID-Nummer haben, ist es tatsächlich dieselbe Liste im Speicher.
n = 3 m = 4 a = [[0] * m] * n a[0][0] = 5 print(a[1][0])
Somit kann eine zweidimensionale Liste nicht einfach durch Wiederholen einer Zeichenkette erzeugt werden. Was ist zu tun?..
Ein möglicher Weg: Sie können eine Liste von n
Elementen (z. B. von n
Nullen) erstellen und dann jedes der Elemente zu einer anderen eindimensionalen Liste von m
Elementen verknüpfen:
n = 3 m = 4 a = [0] * n for i in range(n): a[i] = [0] * m
Ein anderer (aber ähnlicher) Weg: Erstellen Sie eine leere Liste und append
Sie ihr n
mal ein neues Element hinzu (dieses Element sollte eine Liste der Länge m
):
n = 3 m = 4 a = [] for i in range(n): a.append([0] * m)
Der einfachste Weg ist jedoch, den Generator zu verwenden und eine Liste von n
Elementen zu erstellen, von denen jedes eine Liste von m
Nullen ist:
n = 3 m = 4 a = [[0] * m for i in range(n)]
In diesem Fall wird jedes Element unabhängig von den anderen erstellt. Die Liste [0] * m
wird n
mal als die neue erstellt und es findet kein Kopieren von Referenzen statt.
3. Wie geben Sie ein zweidimensionales Array ein?
Nehmen wir an, ein Programm nimmt ein zweidimensionales Array in Form von n
Zeilen an, von denen jedes m
durch Leerzeichen getrennte Zahlen enthält. Wie zwingen Sie das Programm, es zu lesen? Ein Beispiel dafür, wie Sie es tun können:
# Die erste Eingabezeile ist die Anzahl der Zeilen des Arrays n = int(input()) a = [] for i in range(n): a.append([int(j) for j in input().split()])
Oder, ohne raffinierte verschachtelte Aufrufe zu verwenden:
# Die erste Eingabezeile ist die Anzahl der Zeilen des Arrays 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)
Sie können das gleiche mit Generatoren tun:
# Die erste Eingabezeile ist die Anzahl der Zeilen des Arrays n = int(input()) a = [[int(j) for j in input().split()] for i in range(n)]
4. Ein zweidimensionales Array bearbeiten: ein Beispiel
Angenommen, Sie erhalten ein quadratisches Array (ein Array aus n
Zeilen und n
Spalten). Angenommen, Sie müssen Elemente der Hauptdiagonalen gleich 1 setzen (dh die Elemente a[i][j]
für die i==j
), Elemente oberhalb dieser Diagonalen gleich 0 setzen und Elemente setzen unterhalb dieser Diagonalen gleich 2. Das heißt, Sie müssen ein solches Array erzeugen (Beispiel für n==4
):
1 0 0 0 2 1 0 0 2 2 1 0 2 2 2 1(In diesem Fall können Sie dies manuell tun, indem Sie
a[0][0] = 1
, a[0][1] = 0
usw. setzen, aber Sie tun dies nicht manuell für Arrays mit 100 Zeilen und 100 Spalten , die oft der Fall sind.) Wir sind bestrebt, Ihnen verschiedene Möglichkeiten zur Lösung dieses Problems aufzuzeigen. Beachten Sie zunächst, dass Elemente, die über der Hauptdiagonale liegen - Elemente a[i][j]
für die i<j
, und dass für Elemente unterhalb der Hauptdiagonalen i>j
. Somit können wir die Werte i
und j
, die den Wert von a[i][j]
bestimmen. Wir erhalten den folgenden Algorithmus:
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]))
Dieser Algorithmus ist langsam: es werden zwei Schleifen und für jedes Paar (i,j)
ausführt , ein oder zwei , if
Anweisungen. Wenn wir den Algorithmus verkomplizieren, können wir dies ohne eine bedingte Anweisung tun.
Füllen Sie zuerst die Hauptdiagonale, für die wir eine Schleife benötigen:
for i in range(n): a[i][i] = 1
Dann fülle alle Elemente oberhalb der Hauptdiagonalen mit Nullen. Um dies zu erreichen, müssen Sie für jede Zeile mit der Nummer i
einen Wert für a[i][j]
für j
= i+1
, ..., n-1
. Um dies zu tun, benötigen Sie verschachtelte Schleifen:
for i in range(n): for j in range(i + 1, n): a[i][j] = 0
Analog dazu setzen wir für j
= 0
, ..., i-1
die Elemente a[i][j]
gleich 2
:
for i in range(n): for j in range(0, i): a[i][j] = 2
Sie können all diesen Code kombinieren und eine andere Lösung erhalten:
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]))
Hier ist eine andere Lösung, die Listen wiederholt, um die nächsten Zeilen der Liste zu erstellen. Die i
te Zeile der Liste besteht aus i
Zahlen 2
, gefolgt von einer ganzen Zahl 1
, gefolgt von ni-1
Nullen:
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]))
Wie üblich können Sie die Schleife durch den Generator ersetzen:
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. Zweidimensionale Arrays: verschachtelte Generatoren
Sie können verschachtelte Generatoren verwenden, um zweidimensionale Arrays zu erstellen, indem Sie den Generator der Liste, die eine Zeichenfolge ist, innerhalb des Generators aller Zeichenfolgen platzieren. Erinnern Sie sich daran, dass Sie mit dem Generator eine Liste von n
Zeilen und m
Spalten erstellen können (die eine Liste von n
Elementen erzeugt, wobei jedes Element eine Liste von m
Nullen ist):
[[0] * m for i in range(n)]
Die interne Liste kann aber auch beispielsweise mit einem solchen Generator erstellt werden: [0 for j in range(m)]
. Indem wir einen Generator in einen anderen verschachteln, erhalten wir
[[0 for j in range(m)] for i in range(n)]
Wie ist es mit unserem Problem verbunden? Die Sache ist, wenn die Zahl 0 durch einen Ausdruck ersetzt wird, der von i
(der Zeilennummer) und j
(der Spaltennummer) abhängt, erhält man die Matrix nach einer Formel gefüllt.
Angenommen, Sie müssen das folgende Array initialisieren (der Einfachheit halber werden zusätzliche Leerzeichen zwischen Elementen hinzugefügt):
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
In diesem Array gibt es n = 5
Zeilen, m = 6
Spalten, und das Element mit dem Zeilenindex i
und dem Spaltenindex j
wird durch die Formel a[i][j] = i * j
berechnet.
Wie immer könnten Sie einen Generator verwenden, um ein solches Array zu erstellen:
[[i * j for j in range(m)] for i in range(n)]