Wie initialisiere ich ein zweidimensionales Array in Python?

262

Ich beginne mit Python und versuche, eine zweidimensionale Liste zu verwenden, die ich zunächst an jeder Stelle mit derselben Variablen fülle. Ich habe mir das ausgedacht:

def initialize_twodlist(foo):
    twod_list = []
    new = []
    for i in range (0, 10):
        for j in range (0, 10):
            new.append(foo)
        twod_list.append(new)
        new = []

Es gibt das gewünschte Ergebnis, fühlt sich aber wie eine Problemumgehung an. Gibt es eine einfachere / kürzere / elegantere Möglichkeit, dies zu tun?

thepandaatemyface
quelle
7
Nur ein kleiner (oder bedeutender, je nachdem, wer zuschaut) Nitpick: Listen sind keine Arrays. Wenn Sie Arrays möchten, verwenden Sie numpy.
Arnab Datta
Diese Frage ist ähnlich : Sie beschreibt die Initialisierung mehrdimensionaler Arrays in Python.
Anderson Green
@ArnabDatta Wie würden Sie dann ein mehrdimensionales Array in numpy initialisieren?
Anderson Green
1
@AndersonGreen docs.scipy.org/doc/numpy/user/…
Arnab Datta
Sie können Daten in einer Array-ähnlichen Struktur in Standard-Python anordnen, diese ist jedoch bei weitem nicht so effizient oder nützlich wie ein NumPy-Array. Vor allem, wenn Sie mit großen Datenmengen umgehen möchten. Hier ist eine Dokumentation docs.scipy.org/doc/numpy-1.10.1/user/basics.creation.html
jmdeamer

Antworten:

375

Ein Muster, das in Python häufig vorkam, war

bar = []
for item in some_iterable:
    bar.append(SOME EXPRESSION)

Dies hat dazu beigetragen, die Einführung von Listenverständnissen zu motivieren, die dieses Snippet in konvertieren

bar = [SOME EXPRESSION for item in some_iterable]

Das ist kürzer und manchmal klarer. Normalerweise gewöhnt man sich an, diese zu erkennen und Schleifen oft durch Verständnis zu ersetzen.

Ihr Code folgt diesem Muster zweimal

twod_list = []                                       \                      
for i in range (0, 10):                               \
    new = []                  \ can be replaced        } this too
    for j in range (0, 10):    } with a list          /
        new.append(foo)       / comprehension        /
    twod_list.append(new)                           /
Mike Graham
quelle
35
Übrigens kann [[foo] * 10 für x in xrange (10)] verwendet werden, um ein Verständnis loszuwerden. Das Problem ist, dass die Multiplikation eine flache Kopie erstellt, sodass Sie mit new = [foo] * 10 new = [new] * 10 zehnmal eine Liste mit derselben Liste erhalten.
Scott Wolchok
8
Ebenso [foo] * 10ist eine Liste mit genau dem gleichen foo10-fachen, was wichtig sein kann oder nicht.
Mike Graham
2
wir können das einfachste verwenden: wtod_list = [[0 für x in xrange (10))] für x in xrange (10)]
indi60
2
Es tut nie weh, jemandem zu zeigen, wie ein Fisch aussieht.
Csteele5
2
Für Mike Graham Kommentar über [foo] * 10: Das bedeutet , dass dies nicht funktionieren würde , wenn Sie ein Array mit Zufallszahlen sind Füllung (auswertet [random.randint(1,2)] * 10zu [1] * 10oder [2] * 10was bedeutet , dass Sie ein Array aller 1s oder 2s erhalten, anstelle einer zufälligen Anordnung.
Tzu Li
223

Sie können ein Listenverständnis verwenden :

x = [[foo for i in range(10)] for j in range(10)]
# x is now a 10x10 array of 'foo' (which can depend on i and j if you want)
Adam Rosenfield
quelle
1
da die Größe (10) gleich ist, ist es in Ordnung, wenn nicht, muss die verschachtelte Schleife zuerst kommen [foo für j im Bereich (range_of_j)] für i im Bereich (range_of_i)]
Dineshkumar
2
Diese Antwort funktioniert gut , aber mich , da wir Iterierte ifür Zeilen und jfür die Spalten, ich denke , es zu tauschen sollte besser sein iund jzum besseren Verständnis in der Syntax und die Reichweite zu 2 verschiedenen Nummern ändern.
DragonKnight
138

Dieser Weg ist schneller als das Verständnis verschachtelter Listen

[x[:] for x in [[foo] * 10] * 10]    # for immutable foo!

Hier sind einige Python3-Timings für kleine und große Listen

$python3 -m timeit '[x[:] for x in [[1] * 10] * 10]'
1000000 loops, best of 3: 1.55 usec per loop

$ python3 -m timeit '[[1 for i in range(10)] for j in range(10)]'
100000 loops, best of 3: 6.44 usec per loop

$ python3 -m timeit '[x[:] for x in [[1] * 1000] * 1000]'
100 loops, best of 3: 5.5 msec per loop

$ python3 -m timeit '[[1 for i in range(1000)] for j in range(1000)]'
10 loops, best of 3: 27 msec per loop

Erläuterung:

[[foo]*10]*10Erstellt eine Liste desselben Objekts, die zehnmal wiederholt wird. Sie können dies nicht einfach verwenden, da durch Ändern eines Elements dasselbe Element in jeder Zeile geändert wird!

x[:] ist äquivalent zu list(X) , ist aber etwas effizienter, da die Namenssuche vermieden wird. In beiden Fällen wird eine flache Kopie jeder Zeile erstellt, sodass jetzt alle Elemente unabhängig sind.

Alle Elemente sind jedoch dasselbe fooObjekt. Wenn fooes also veränderbar ist , können Sie dieses Schema nicht verwenden. Sie müssten es verwenden

import copy
[[copy.deepcopy(foo) for x in range(10)] for y in range(10)]

oder eine Klasse (oder Funktion) annehmen Foo, die foos zurückgibt

[[Foo() for x in range(10)] for y in range(10)]
John La Rooy
quelle
4
@ Mike, hast du den fett gedruckten Teil verpasst? Wenn foo veränderlich ist, funktioniert keine der anderen Antworten hier (es sei denn, Sie mutieren foo überhaupt nicht)
John La Rooy
1
Sie können beliebige Objekte mit nicht korrekt kopieren copy.deepcopy. Sie benötigen einen für Ihre Daten spezifischen Plan, wenn Sie ein beliebiges veränderbares Objekt haben.
Mike Graham
1
Wenn Sie Geschwindigkeit so dringend in einer Schleife benötigen, kann es Zeit sein, Cython, Webart oder ähnliches zu verwenden ...
james.haggerty
1
@ JohnLaRooy ich denke du hast ausgetauscht xund y. Sollte es nicht sein[[copy.deepcopy(foo) for y in range(10)] for x in range(10)]
user3085931
1
@Nils erstellt [foo]*10keine 10 verschiedenen Objekte - aber es ist leicht, den Unterschied zu übersehen, wenn foo unveränderlich ist, wie ein intoder str.
John La Rooy
137

Nicht benutzen [[v]*n]*n, es ist eine Falle!

>>> a = [[0]*3]*3
>>> a
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]

aber

    t = [ [0]*3 for i in range(3)]

funktioniert super.

Jason CHAN
quelle
26
Ja, ich bin auch in diese Falle geraten. Es *liegt daran, dass addressdas Objekt (Liste) kopiert wird .
chinuy
1
Upvoted, da mich das erwischt hat. Um klarer zu sein , [[0] * col for _ in range(row)].
Abhijit Sarkar
62

So initialisieren Sie ein zweidimensionales Array in Python:

a = [[0 for x in range(columns)] for y in range(rows)]
Vipul
quelle
4
Um alle Werte auf 0 zu initialisieren, verwenden Sie einfach a = [[0 for x in range(columns)] for y in range(rows)].
ZX9
27
[[foo for x in xrange(10)] for y in xrange(10)]
Ignacio Vazquez-Abrams
quelle
1
xrange () wurde in python3.5
MiaeKim
warum das nicht funktioniert: [0 * col] * row. Wenn ich ein Element ändere, wird es an anderen Stellen repliziert. Aber ich verstehe nicht warum?
Code Muncher
Denn das macht genau das Gleiche wie der Code in der Frage.
Ignacio Vazquez-Abrams
2
@codemuncher Der Grund, warum Sie [[0] * col] * rownicht das tun, was Sie wollen, ist, dass Python beim Initialisieren einer 2D-Liste auf diese Weise nicht für jede Zeile unterschiedliche Kopien erstellt. Stattdessen wird die äußere Liste mit Zeigern auf dieselbe Kopie von initiiert [0]*col. Jede Änderung, die Sie an einer der Zeilen vornehmen, wird dann in den verbleibenden Zeilen wiedergegeben, da alle tatsächlich auf dieselben Daten im Speicher verweisen.
Addie
Nur ein Gedanke, aber sind all diese Listen nicht gut zum Anhängen geeignet? Dh. Wenn ich eine leere 2D-Liste der Dimension 3 * 6 möchte und an Index [0] [0], [1] [0], [2] [0] usw. anhängen möchte, um alle 18 Elemente auszufüllen, keines von Diese Antworten werden richtig funktionieren?
mLstudent33
22

Wenn Sie mehrdimensionale Arrays möchten, möchten Sie normalerweise keine Liste von Listen, sondern ein numpy-Array oder möglicherweise ein Diktat.

Zum Beispiel würden Sie mit numpy so etwas tun

import numpy
a = numpy.empty((10, 10))
a.fill(foo)
Mike Graham
quelle
2
Obwohl numpyes großartig ist, denke ich, dass es für einen Anfänger ein bisschen übertrieben sein könnte.
Esteban Küber
3
numpy bietet einen mehrdimensionalen Array-Typ. Das Erstellen eines guten mehrdimensionalen Arrays aus Listen ist möglich, aber für Anfänger weniger nützlich und schwieriger als die Verwendung von Numpy. Verschachtelte Listen eignen sich hervorragend für einige Anwendungen, sind jedoch normalerweise nicht das, womit jemand, der ein 2D-Array möchte, am besten zurechtkommt.
Mike Graham
1
Nach einigen Jahren, in denen gelegentlich ernsthafte Python-Apps erstellt wurden, scheinen die Macken von Standard-Python-Arrays zu rechtfertigen, einfach weiterzumachen numpy. +1
Javadba
12

Sie können genau das tun:

[[element] * numcols] * numrows

Beispielsweise:

>>> [['a'] *3] * 2
[['a', 'a', 'a'], ['a', 'a', 'a']]

Dies hat jedoch einen unerwünschten Nebeneffekt:

>>> b = [['a']*3]*3
>>> b
[['a', 'a', 'a'], ['a', 'a', 'a'], ['a', 'a', 'a']]
>>> b[1][1]
'a'
>>> b[1][1] = 'b'
>>> b
[['a', 'b', 'a'], ['a', 'b', 'a'], ['a', 'b', 'a']]
hithwen
quelle
11
Nach meiner Erfahrung führt dieser "unerwünschte" Effekt häufig zu sehr schlechten logischen Fehlern. Meiner Meinung nach sollte dieser Ansatz vermieden werden, stattdessen ist die Antwort von @ Vipul viel besser.
Alan Turing
Dieser Ansatz funktioniert gut. Warum verweisen manche Leute in Kommentaren darauf, dass er genauso schlecht ist?
Bravo
1
Aufgrund der unerwünschten Nebenwirkung können Sie es nicht wirklich als Matrix behandeln. Wenn Sie den Inhalt nicht ändern müssen, ist alles in Ordnung.
Hithwen
9
twod_list = [[foo for _ in range(m)] for _ in range(n)]

denn n ist die Anzahl der Zeilen und m ist die Anzahl der Spalten und foo ist der Wert.

Moustafa Saleh
quelle
8

Wenn es sich um ein dünn besiedeltes Array handelt, ist es möglicherweise besser, ein Wörterbuch mit einem Tupel zu verwenden:

dict = {}
key = (a,b)
dict[key] = value
...
btk
quelle
5
t = [ [0]*10 for i in [0]*10]

Für jedes Element wird ein neues [0]*10erstellt.

user9269722
quelle
4

Falscher Ansatz: [[Keine * m] * n]

>>> m, n = map(int, raw_input().split())
5 5
>>> x[0][0] = 34
>>> x
[[34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None], [34, None, None, None, None]]
>>> id(x[0][0])
140416461589776
>>> id(x[3][0])
140416461589776

Bei diesem Ansatz erlaubt Python nicht, einen anderen Adressraum für die äußeren Spalten zu erstellen, und führt zu verschiedenen Fehlverhalten als erwartet.

Richtiger Ansatz, aber mit Ausnahme:

y = [[0 for i in range(m)] for j in range(n)]
>>> id(y[0][0]) == id(y[1][0])
False

Es ist ein guter Ansatz, aber es gibt eine Ausnahme, wenn Sie den Standardwert auf setzen None

>>> r = [[None for i in range(5)] for j in range(5)]
>>> r
[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]]
>>> id(r[0][0]) == id(r[2][0])
True

Stellen Sie Ihren Standardwert mit diesem Ansatz richtig ein.

Absolut richtig:

Folgen Sie der Antwort des Mikrofons auf Doppelschleife .

Patilnitin
quelle
3
Matrix={}
for i in range(0,3):
  for j in range(0,3):
    Matrix[i,j] = raw_input("Enter the matrix:")
Sparsh
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
Ajean
3

So initialisieren Sie ein zweidimensionales Array: arr = [[]*m for i in range(n)]

tatsächlich, arr = [[]*m]*n wird ein 2D-Array erstellt, in dem alle n Arrays auf dasselbe Array verweisen, sodass jede Wertänderung in einem Element in allen n Listen berücksichtigt wird

Weitere Erklärungen finden Sie unter: https://www.geeksforgeeks.org/python-using-2d-arrays-lists-the-right-way/

Abhimanyu
quelle
3

Verwenden Sie den einfachsten Gedanken, um dies zu erstellen.

wtod_list = []

und füge die Größe hinzu:

wtod_list = [[0 for x in xrange(10)] for x in xrange(10)]

oder wenn wir zuerst die Größe deklarieren wollen. wir verwenden nur:

   wtod_list = [[0 for x in xrange(10)] for x in xrange(10)]
indi60
quelle
1

Wie @Arnab und @Mike betonten, ist ein Array keine Liste. Es gibt nur wenige Unterschiede: 1) Arrays haben während der Initialisierung eine feste Größe. 2) Arrays unterstützen normalerweise weniger Operationen als eine Liste.

In den meisten Fällen vielleicht ein Overkill, aber hier ist eine grundlegende 2D-Array-Implementierung, die die Hardware-Array-Implementierung mithilfe von Python-C-Typen (C-Bibliotheken) nutzt.

import ctypes
class Array:
    def __init__(self,size,foo): #foo is the initial value
        self._size = size
        ArrayType = ctypes.py_object * size
        self._array = ArrayType()
        for i in range(size):
            self._array[i] = foo
    def __getitem__(self,index):
        return self._array[index]
    def __setitem__(self,index,value):
        self._array[index] = value
    def __len__(self):
        return self._size

class TwoDArray:
    def __init__(self,columns,rows,foo):
        self._2dArray = Array(rows,foo)
        for i in range(rows):
            self._2dArray[i] = Array(columns,foo)

    def numRows(self):
        return len(self._2dArray)
    def numCols(self):
        return len((self._2dArray)[0])
    def __getitem__(self,indexTuple):
        row = indexTuple[0]
        col = indexTuple[1]
        assert row >= 0 and row < self.numRows() \
               and col >=0 and col < self.numCols(),\
               "Array script out of range"
        return ((self._2dArray)[row])[col]

if(__name__ == "__main__"):
    twodArray = TwoDArray(4,5,5)#sample input
    print(twodArray[2,3])
Antony Thomas
quelle
1

Das Wichtige, was ich verstanden habe, ist: Beim Initialisieren eines Arrays (in einer beliebigen Dimension) sollten wir allen Positionen des Arrays einen Standardwert geben. Dann ist nur die Initialisierung abgeschlossen. Danach können wir an jeder Position des Arrays neue Werte ändern oder empfangen. Der folgende Code hat bei mir perfekt funktioniert

N=7
F=2

#INITIALIZATION of 7 x 2 array with deafult value as 0
ar=[[0]*F for x in range(N)]

#RECEIVING NEW VALUES TO THE INITIALIZED ARRAY
for i in range(N):
    for j in range(F):
        ar[i][j]=int(input())
print(ar)
Fairoos Ok
quelle
1

Wenn Sie numpy verwenden , können Sie problemlos 2D-Arrays erstellen:

import numpy as np

row = 3
col = 5
num = 10
x = np.full((row, col), num)

x

array([[10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10],
       [10, 10, 10, 10, 10]])
Mehmet Emin Yıldırım
quelle
1
row=5
col=5
[[x]*col for x in [b for b in range(row)]]

Das Obige gibt Ihnen ein 5x5 2D-Array

[[0, 0, 0, 0, 0],
 [1, 1, 1, 1, 1],
 [2, 2, 2, 2, 2],
 [3, 3, 3, 3, 3],
 [4, 4, 4, 4, 4]]

Es verwendet das Verständnis verschachtelter Listen. Aufschlüsselung wie folgt:

[[x]*col for x in [b for b in range(row)]]

[x] * col -> endgültiger Ausdruck, der
für x in -> x ausgewertet wird, ist der vom Iterator bereitgestellte Wert
[b für b im Bereich (Zeile)] -> Iterator.

[b für b im Bereich (Zeile)]] wird dies zu [0,1,2,3,4] ausgewertet, da Zeile = 5 ist,
so dass es jetzt vereinfacht wird

[[x]*col for x in [0,1,2,3,4]]

Dies ergibt [[0] * 5 für x in [0,1,2,3,4]] -> mit x = 0 1. Iteration
[[1] * 5 für x in [0,1,2, 3,4]] -> mit x = 1 2. Iteration
[[2] * 5 für x in [0,1,2,3,4]] -> mit x = 2 3. Iteration
[[3] * 5 für x in [0,1,2,3,4]] -> mit x = 3 4. Iteration
[[4] * 5 für x in [0,1,2,3,4]] -> mit x = 4 5. Iteration

Satya
quelle
0

Dies ist das Beste, was ich gefunden habe, um neue Programmierer zu unterrichten und ohne zusätzliche Bibliotheken zu verwenden. Ich hätte gerne etwas Besseres.

def initialize_twodlist(value):
    list=[]
    for row in range(10):
        list.append([value]*10)
    return list
Paul Vincent Craven
quelle
0

Hier ist ein einfacher Weg:

import numpy as np
twoD = np.array([[]*m]*n)

Verwenden Sie zum Initialisieren aller Zellen mit einem beliebigen 'x'-Wert:

twoD = np.array([[x]*m]*n
user3650331
quelle
0

Oft verwende ich diesen Ansatz zum Initialisieren eines zweidimensionalen Arrays

n=[[int(x) for x in input().split()] for i in range(int(input())]


quelle
0

Das allgemeine Muster zum Hinzufügen von Dimensionen könnte aus dieser Reihe gezogen werden:

x = 0
mat1 = []
for i in range(3):
    mat1.append(x)
    x+=1
print(mat1)


x=0
mat2 = []
for i in range(3):
    tmp = []
    for j in range(4):
        tmp.append(x)
        x+=1
    mat2.append(tmp)

print(mat2)


x=0
mat3 = []
for i in range(3):
    tmp = []
    for j in range(4):
        tmp2 = []
        for k in range(5):
            tmp2.append(x)
            x+=1
        tmp.append(tmp2)
    mat3.append(tmp)

print(mat3)
Juanfal
quelle
Willkommen bei SO. Diese Frage hat bereits eine massiv nach oben akzeptierte Antwort. Auf den ersten Blick beantwortet dieser Beitrag die Frage nicht wirklich. Weitere Informationen finden Sie unter stackoverflow.com/help/how-to-answer .
Nick
0

Sie können dies versuchen [[0] * 10] * 10. Dies gibt das 2d-Array mit 10 Zeilen und 10 Spalten mit dem Wert 0 für jede Zelle zurück.

ishant
quelle
Dies ist im Wesentlichen die gleiche Antwort wie stackoverflow.com/a/25601284/2413201 ...
Armali
2
Dadurch wird ein Array mit 10 Zeigern auf dieselbe Zeile erstellt. Wenn Sie dies tun a = [[0]*10]*10und dann sehen a[0][0] = 1Sie das erste Element in jeder Zeile jetzt gleich 1
andnik
0

lst = [[0] * m für i im Bereich (n)]

Initialisieren Sie alle Matrix n = Zeilen und m = Spalten

HRITIK RAJENDRA AKOLKAR
quelle
Können Sie bitte Code als Code formatieren? Es wäre viel besser lesbar.
Thomas
0

Eine andere Möglichkeit besteht darin, ein Wörterbuch zu verwenden, um ein zweidimensionales Array aufzunehmen.

twoD = {}
twoD[0,0] = 0
print(twoD[0,0]) # ===> prints 0

Dies kann nur beliebige 1D-, 2D-Werte enthalten. Um dies mit 0einem anderen int-Wert zu initialisieren , verwenden Sie Sammlungen .

import collections
twoD = collections.defaultdict(int)
print(twoD[0,0]) # ==> prints 0
twoD[1,1] = 1
print(twoD[1,1]) # ==> prints 1
Tej91
quelle
0

Code:

num_rows, num_cols = 4, 2
initial_val = 0
matrix = [[initial_val] * num_cols for _ in range(num_rows)]
print(matrix) 
# [[0, 0], [0, 0], [0, 0], [0, 0]]

initial_val muss unveränderlich sein.

Abhishek Bhatia
quelle
-3
from random import randint
l = []

for i in range(10):
    k=[]
    for j in range(10):
        a= randint(1,100)
        k.append(a)

    l.append(k)




print(l)
print(max(l[2]))

b = []
for i in range(10):
    a = l[i][5]
    b.append(a)

print(min(b))
KANDARP JAYESH SHAH
quelle
4
Bitte fügen Sie einen Text hinzu, der beschreibt, was Ihr Code tut.
Whackamadoodle3000
1
Normalerweise ist es besser, eine Lösung zu erklären, als nur einige Zeilen anonymen Codes zu veröffentlichen. Sie können lesen, wie ich eine gute Antwort schreibe und wie Sie vollständig codebasierte Antworten erklären .
Massimiliano Kraus