2014-07-10 24 views
7

Pracuję nad listą list i dostęp do kolumn jest bardzo mylące.Dlaczego x [i] [:] = x [:] [i] gdzie x to lista list?

Załóżmy X jest zdefiniowana w następujący sposób:

x = [[int(np.random.rand()*100) for i in xrange(5)] for x in xrange(10)] 
    pprint.pprint(x) 
[[86, 92, 95, 78, 68], 
[76, 80, 44, 30, 73], 
[48, 85, 99, 35, 14], 
[3, 84, 50, 39, 47], 
[3, 7, 67, 28, 65], 
[19, 13, 98, 53, 33], 
[9, 97, 35, 25, 89], 
[48, 3, 48, 5, 1], 
[21, 40, 72, 61, 62], 
[58, 43, 84, 69, 26]] 

Teraz zarówno x[1][:] i x[:][1] dają ten sam wynik:

[76, 80, 44, 30, 73] 

Może ktoś wyjaśnić, dlaczego? Dziękuję

+2

Dlaczego używasz listy list? Masz NumPy! Używasz generatora liczb losowych NumPy! Użyj tablicy! Gdybyś miał tablicę zamiast listy list, 'x [i,:]' i 'x [:, i]' zrobiłyby to, co chcesz. – user2357112

+0

Ponieważ mam listy różnych rozmiarów i typów, a przykład tutaj jest tylko ilustracyjny. – ipluto

Odpowiedz

6

Zachowanie jest bardzo proste do zrozumienia, jeśli dzieli się dwie operacje indeksowania każdego z wyrażeń na osobne części.

  • x[1] będzie druga wartość z listy list (lista [76, 80, 44, 30, 73]).
  • x[1][:] to kopia x[1] (fragment obejmujący całą listę).
  • x[:] to (płytka) kopia x (lista list).
  • x[:][1] to druga wartość z skopiowanej listy list, która jest tym samym obiektem, co x[1].

Te dwa wyrażenia działają tak samo. Zauważ, że ponieważ pierwsze wyrażenie kopiuje listę (z plasterkiem [:] na końcu), nie są one tym samym obiektem (x[1][:] is x[:][1] będzie False).

Jeśli uzywasz 2D numpy tablicy, można uzyskać różne zachowanie, ponieważ można pokroić w dowolnych wymiarach (z wykorzystaniem nieco innej składni):

import numpy as np 

x = np.array([[86, 92, 95, 78, 68], 
       [76, 80, 44, 30, 73], 
       [48, 85, 99, 35, 14], 
       [3, 84, 50, 39, 47], 
       [3, 7, 67, 28, 65], 
       [19, 13, 98, 53, 33], 
       [9, 97, 35, 25, 89], 
       [48, 3, 48, 5, 1], 
       [21, 40, 72, 61, 62], 
       [58, 43, 84, 69, 26]]) 

print(x[1,:]) # prints the values of the second row: [76 80 44 30 73] 
print(x[:,1]) # prints the values of the second column: [92 80 85 84 7 13 97 3 40 43] 

To może być to, czego szukali.

+0

Dziękuję za szczegółowe wyjaśnienie. Zdecydowanie użyłbym np.array, gdyby nie różne listy, które mam na mojej oryginalnej liście. – ipluto

3

x[:][1] jest cały wiersz tablicy 1 i x[1][:] wszystko jest rzędu 1 z x więc oboje punkt w tym samym wierszu.

In [2]: x[:] 
Out[2]: 
[[86, 92, 95, 78, 68], 
[76, 80, 44, 30, 73], 
[48, 85, 99, 35, 14], 
[3, 84, 50, 39, 47], 
[3, 7, 67, 28, 65], 
[19, 13, 98, 53, 33], 
[9, 97, 35, 25, 89], 
[48, 3, 48, 5, 1], 
[21, 40, 72, 61, 62], 
[58, 43, 84, 69, 26]] 
In [3]: x[1] 
Out[3]: [76, 80, 44, 30, 73] 

In [4]: x[1][:] 
Out[4]: [76, 80, 44, 30, 73] 

Korzystanie x[:] jest często stosowane, jeżeli chcesz zapisać kopię x w zmiennej i nie tylko odniesienie do niej:

In [6]: x1 = x[:] 

In [7]: x1 
Out[7]: 
[[86, 92, 95, 78, 68], 
[76, 80, 44, 30, 73], 
[48, 85, 99, 35, 14], 
[3, 84, 50, 39, 47], 
[3, 7, 67, 28, 65], 
[19, 13, 98, 53, 33], 
[9, 97, 35, 25, 89], 
[48, 3, 48, 5, 1], 
[21, 40, 72, 61, 62], 
[58, 43, 84, 69, 26]] 

Tworzenie kopii:

In [11]: x1 = x[:] 
In [12]: id(x1)  # different objects so different id's 
Out[12]: 140130415845104  
In [13]: id(x) 
Out[13]: 140130400510176 

Tworzenie odniesienia:

In [14]: x1 = x 

In [15]: id(x) # same object so same id's 
Out[15]: 140130400510176 

In [16]: id(x1) 
Out[16]: 140130400510176 
1

x[1][:] mówi najpierw uzyskać x[1], który jest pierwszym obiektem na liście. W tym przypadku jest to lista. Następnie, dodając do tego [:], mówisz, że chcesz zwrócić wszystkie obiekty listy z pierwszej listy. Więc zwraca cały pierwszy obiekt listy z głównej listy list.

x[:][1] najpierw mówi przez x[:], aby zwrócić całą listę. Następnie dodając [1] mówisz, że zwracasz tylko pierwszy element na całej liście.

Powiązane problemy