Zaczynam python i próbuję użyć dwuwymiarowej listy, którą początkowo wypełniam tą samą zmienną w każdym miejscu. Wymyśliłem to:
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 = []
Daje pożądany efekt, ale wydaje się obejściem. Czy jest na to łatwiejszy / krótszy / bardziej elegancki sposób?
python
multidimensional-array
thepandaatemyface
źródło
źródło
Odpowiedzi:
Wzorem, który często pojawiał się w Pythonie, był
który pomógł zmotywować wprowadzenie wyrażeń listowych, które przekonwertują ten fragment
który jest krótszy, a czasem jaśniejszy. Zwykle przyzwyczajasz się do ich rozpoznawania i często zastępujesz pętle zrozumieniem.
Twój kod jest dwa razy zgodny z tym wzorcem
źródło
[foo] * 10
jest lista z dokładnie taką samąfoo
10 razy, co może, ale nie musi być ważne.[foo] * 10
: Oznacza to, że to nie zadziała, jeśli wypełnisz tablicę liczbami losowymi (ocenia[random.randint(1,2)] * 10
na[1] * 10
lub[2] * 10
co oznacza, że otrzymujesz tablicę wszystkich 1 lub 2 zamiast losowej tablicy.Możesz użyć rozumienia listy :
źródło
i
dla wierszy ij
kolumn, myślę, że lepiej jest zamienići
i zastosowaćj
składnię, aby lepiej zrozumieć i zmienić zakres na 2 różne liczby.Ta metoda jest szybsza niż interpretacja listy zagnieżdżonej
Oto niektóre czasy Python3 dla małych i dużych list
Wyjaśnienie:
[[foo]*10]*10
tworzy listę tego samego obiektu powtarzaną 10 razy. Nie możesz tego po prostu użyć, ponieważ modyfikacja jednego elementu spowoduje zmodyfikowanie tego samego elementu w każdym wierszu!x[:]
jest równoważne,list(X)
ale jest nieco bardziej wydajne, ponieważ pozwala uniknąć wyszukiwania nazw. Tak czy inaczej, tworzy płytką kopię każdego wiersza, więc teraz wszystkie elementy są niezależne.Wszystkie elementy są tym samym
foo
obiektem, więc jeślifoo
można go modyfikować , nie możesz użyć tego schematu., Musisz użyćlub przyjęcie klasy (lub funkcji),
Foo
która zwracafoo
sźródło
copy.deepcopy
. Potrzebujesz planu specyficznego dla swoich danych, jeśli masz dowolny obiekt, który można modyfikować.x
iy
. Nie powinno tak być[[copy.deepcopy(foo) for y in range(10)] for x in range(10)]
[foo]*10
nie tworzy 10 różnych obiektów - ale łatwo przeoczyć różnicy w przypadku, gdy foo jest niezmienne, jak uint
lubstr
.Nie używaj
[[v]*n]*n
, to pułapka!ale
działa świetnie.
źródło
*
kopiujeaddress
obiekt (listę).[[0] * col for _ in range(row)]
.Aby zainicjować tablicę dwuwymiarową w Pythonie:
źródło
a = [[0 for x in range(columns)] for y in range(rows)]
.źródło
[[0] * col] * row
nie robisz tego, co chcesz, jest to, że po zainicjowaniu listy 2D w ten sposób Python nie utworzy odrębnych kopii każdego wiersza. Zamiast tego zainicjuje zewnętrzną listę ze wskaźnikami do tej samej kopii[0]*col
. Wszelkie zmiany dokonane w jednym z wierszy zostaną odzwierciedlone w pozostałych wierszach, ponieważ wszystkie one faktycznie wskazują te same dane w pamięci.Zwykle, gdy potrzebujesz tablic wielowymiarowych, nie potrzebujesz listy list, a raczej tablicy numpy lub ewentualnie dyktanda.
Na przykład za pomocą numpy zrobiłbyś coś takiego
źródło
numpy
jest świetny, myślę, że dla początkującego może to być trochę przesada.numpy
. +1Możesz to zrobić:
Na przykład:
Ale ma to niepożądany efekt uboczny:
źródło
dla n oznacza liczbę wierszy, a m jest liczbą kolumn, a foo jest wartością.
źródło
Jeśli jest to tablica słabo zaludniona, lepiej byłoby użyć słownika z krotką:
źródło
dla każdego elementu
[0]*10
zostanie utworzony nowy ..źródło
Niepoprawne podejście: [[None * m] * n]
Dzięki takiemu podejściu python nie pozwala na tworzenie innej przestrzeni adresowej dla zewnętrznych kolumn i doprowadzi do innego niewłaściwego zachowania niż się spodziewasz.
Prawidłowe podejście, ale z wyjątkiem:
Jest to dobre podejście, ale istnieje wyjątek, jeśli ustawisz wartość domyślną na
None
Więc ustaw poprawnie wartość domyślną, stosując to podejście.
Absolutnie poprawne:
Postępuj zgodnie z odpowiedzią Mike'a dotyczącą podwójnej pętli .
źródło
źródło
Aby zainicjować tablicę dwuwymiarową, użyj:
arr = [[]*m for i in range(n)]
faktycznie
arr = [[]*m]*n
stworzy tablicę 2D, w której wszystkie n tablic wskaże tę samą tablicę, więc każda zmiana wartości w dowolnym elemencie zostanie odzwierciedlona na wszystkich n listachwięcej dalszych wyjaśnień na stronie: https://www.geeksforgeeks.org/python-using-2d-arrays-lists-the-right-way/
źródło
użyj najprostszej myśli, aby to stworzyć.
i dodaj rozmiar:
lub jeśli chcemy najpierw zadeklarować rozmiar. używamy tylko:
źródło
Jak zauważyli @Arnab i @Mike, tablica nie jest listą. Kilka różnic to 1) tablice mają ustalony rozmiar podczas inicjalizacji 2) tablice zwykle obsługują mniejsze operacje niż lista.
Może w większości przypadków przesada, ale tutaj jest podstawowa implementacja tablicy 2d, która wykorzystuje sprzętową implementację tablicy przy użyciu ctypów python (bibliotek c)
źródło
Ważną rzeczą, którą zrozumiałem, jest: Podczas inicjowania tablicy (w dowolnym wymiarze) powinniśmy nadać domyślną wartość wszystkim pozycjom tablicy. Następnie kończy się tylko inicjalizacja. Następnie możemy zmienić lub otrzymać nowe wartości do dowolnej pozycji tablicy. Poniższy kod działał dla mnie idealnie
źródło
Jeśli używasz numpy , możesz łatwo tworzyć tablice 2D:
x
źródło
Powyższe daje macierz 2D 5x5
Korzysta ze zrozumienia listy zagnieżdżonej. Podział jak poniżej:
[x] * col -> końcowe wyrażenie, które jest oceniane
dla x w -> x będzie wartością podaną przez iterator
[b dla bw zakresie (wiersz)]] -> Iterator.
[b dla bw przedziale (rzędzie)]] spowoduje to ocenę do [0,1,2,3,4], ponieważ wiersz = 5,
więc teraz upraszcza się
Będzie to oceniać na [[0] * 5 dla x w [0,1,2,3,4]] -> przy x = 0 1. iteracja
[[1] * 5 dla x w [0,1,2, 3,4]] -> przy x = 1 2. iteracja
[[2] * 5 dla x w [0,1,2,3,4]] -> przy x = 2 3. iteracja
[[3] * 5 dla x w [0,1,2,3,4]] -> przy x = 3 4. iteracja
[[4] * 5 dla x w [0,1,2,3,4]] -> z x = 4 5. iteracja
źródło
To najlepsze, jakie znalazłem do nauczania nowych programistów i bez korzystania z dodatkowych bibliotek. Chciałbym jednak coś lepszego.
źródło
Oto łatwiejszy sposób:
Do zainicjowania wszystkich komórek dowolną wartością „x” użyj:
źródło
Często używam tego podejścia do inicjowania tablicy dwuwymiarowej
n=[[int(x) for x in input().split()] for i in range(int(input())]
źródło
Ogólny wzór dodawania wymiarów można narysować z tej serii:
źródło
Możesz spróbować tego [[0] * 10] * 10. Zwróci tablicę 2d 10 wierszy i 10 kolumn o wartości 0 dla każdej komórki.
źródło
a = [[0]*10]*10
, a następniea[0][0] = 1
widać, że pierwszy element w każdym wierszu teraz równa 1lst = [[0] * m dla i w zakresie (n)]
zainicjuj całą macierz n = wiersze im = kolumny
źródło
Innym sposobem jest użycie słownika do przechowywania tablicy dwuwymiarowej.
Może to po prostu przechowywać dowolne wartości 1D, 2D i aby zainicjować tę wartość
0
lub dowolną inną wartość int, użyj kolekcji .źródło
Kod:
initial_val
musi być niezmienny.źródło
źródło