2012-02-27 14 views
15

Powiedzmy mam następujący pusty dwuwymiarowej tablicy w Pythonie:wartość Przypisanie do pojedynczej komórki w tablicy dwuwymiarowej Pythona

q = [[None]*5]*4 

chcę przypisać wartość 5 do pierwszego rzędu w pierwszym kolumna q. Instynktownie, I wykonaj następujące czynności:

q[0][0] = 5 

Jednak ta produkuje:

[[5, None, None, None, None], 
    [5, None, None, None, None], 
    [5, None, None, None, None], 
    [5, None, None, None, None]] 

Pierwszym elementem każdym tablicy jest inicjowany 5, gdzie myślałem, że tylko pierwszy element pierwszego array otrzyma aktualizację. Mam dwa pytania:

  1. Dlaczego Python inicjuje pierwszą wartość każdej tablicy, a nie tylko pierwszą?
  2. Czy istnieje lepszy sposób na wykonanie tego, co próbuję wykonać?

Odpowiedz

31

nie robić to, czego się spodziewano.

q = [[None]*5]*4 

Ponownie korzysta z obiektów list. Jak widać po dokonaniu zmiany w jednej komórce, która znajdowała się w ponownie wykorzystanym obiekcie listy.

Pojedyncza lista o wartości [None] służy pięć razy.

Pojedyncza lista o wartości [[None]*5] służy czterokrotnie.

q = [ [ None for i in range(5) ] for j in range(4) ] 

Może być więcej, czego szukasz.

To wyraźnie zapobiega ponownemu użyciu obiektu listy.

80% czasu, słownik jest tym, czego naprawdę chcesz.

q = {} 
q[0,0]= 5 

Będzie również działać. Nie rozpoczynasz od wstępnie zdefiniowanej siatki wartości None. Ale rzadko ich potrzebuję.

W języku Python w wersji 2.7 lub wyższej możesz to zrobić.

q = { (i,j):0 for i in range(5) for j in range(4) } 

To spowoduje zbudowanie siatki indeksowanej przez 2-krotne.

{(0, 1): 0, (1, 2): 0, (3, 2): 0, (0, 0): 0, (3, 3): 0, (3, 0): 0, (3, 1): 0, (2, 1): 0, (0, 2): 0, (2, 0): 0, (1, 3): 0, (2, 3): 0, (4, 3): 0, (2, 2): 0, (1, 0): 0, (4, 2): 0, (0, 3): 0, (4, 1): 0, (1, 1): 0, (4, 0): 0} 
+0

+1 dla słownika jako matrycy. –

+1

Dam ci +1, jeśli podzielisz się wynikami badań, które doprowadziły do ​​tej wartości 80%. –

+2

To zasada Pareto. http://en.wikipedia.org/wiki/Pareto_principle. 80% czasu potrzebujesz tylko 20% struktur danych. –

5

Powód, dla którego masz listę, po prostu powielono cztery razy! Python nie odtwarza tej listy za każdym razem, gdy wykonujesz *4. Używa tego samego obiektu listy.

Aby obejść ten problem, należy do siły pytona do regenrate tę listę dla ciebie za każdym razem:

[ [None] * 5 for i1 in range(4) ] 

W tym przypadku używam listowych.

0

Dlaczego Python inicjuje pierwszą wartość każdej tablicy, a nie tylko pierwszą?

Ponieważ są to te same tablice, do których odnosi się wiele razy.

Czy istnieje lepszy sposób na wykonanie tego, co próbuję zrobić?

Utwórz strukturę w taki sposób, że zewnętrzna tablica odwołuje się do oddzielnych wewnętrznych tablic, zamiast używać ich ponownie. Inne odpowiedzi zapewniają sposoby na zrobienie tego.

1

Odpowiedź jest prosta Nigdy nie używaj

q = [[None]*5]*4 

jak wtedy, gdy przydział zadania

q[0][1]=5 przypisuje wartość wielokrotnego czas do wielu wierszy w 1 kolumna try druku (q)

raczej używać

q = { (i,j):0 for i in range(5) for j in range(4) } 

następnie q[0][1]=5 przydzieli tylko jeden raz spróbować

print(q) 
2
q = [[None]*5]*4 
print(q) 
q[1][1]=4 
print(q) 
q = [ [ None for i in range(5) ] for j in range(4) ] 
q[1][1]=4 
print(q) 

wynik:

[[None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None], [None, None, None, None, None]] 
[[None, 4, None, None, None], [None, 4, None, None, None], [None, 4, None, None, None], [None, 4, None, None, None]] 
[[None, None, None, None, None], [None, 4, None, None, None], [None, None, None, None, None], [None, None, None, None, None]] 
0

W przypadku, gdy chcesz skorzystać z listy, a nie słownika jak inni proponują można użyć to:

q[0] = [5,None,None,None,None] 
0

Odpowiedź na pytanie numer 2: Używanie numpy jest opcją. Zobacz poniższy kod.

import numpy as np 

# creating 2D array with nans 
num_of_rows = 5 
num_of_cols = 3 
a = np.full((num_of_rows, num_of_cols), np.nan) 
#for zero vals: a = np.zeros((num_of_rows, num_of_cols)) 

# placing number 5 in row 3, col 1 
value = [5] 
position_row = 3 
position_col = 1 
# the put command below flattens the 2D array 
position = [int(num_of_cols * position_row + position_col)] 
np.put(a, position, value) 

Wynik:

[[ nan nan nan] 
[ nan nan nan] 
[ nan nan nan] 
[ nan 5. nan] 
[ nan nan nan]] 
Powiązane problemy