2010-07-22 16 views
61

Próbuję uzyskać n-te elementy z listy krotek.Jak wyodrębnić n-te elementy z listy krotek w python?

mam coś takiego:

elements = [(1,1,1),(2,3,7),(3,5,10)] 

życzę, aby wyodrębnić tylko drugi elementów każdej krotki do listy:

seconds = [1, 3, 5] 

Wiem, że można to zrobić z for pętli ale Chciałem wiedzieć, czy jest inny sposób, ponieważ mam tysiące krotek.

Odpowiedz

123
[x[1] for x in elements] 
23

Wiem, że można to zrobić z za, ale chciałem wiedzieć, czy istnieje inny sposób

Jest też inny sposób. Można również zrobić to z map i itemgetter:

>>> from operator import itemgetter 
>>> map(itemgetter(1), elements) 

ten nadal wykonuje pętlę wewnętrznie chociaż i to jest nieco wolniejszy niż listowego:

setup = 'elements = [(1,1,1) for _ in range(100000)];from operator import itemgetter' 
method1 = '[x[1] for x in elements]' 
method2 = 'map(itemgetter(1), elements)' 

import timeit 
t = timeit.Timer(method1, setup) 
print('Method 1: ' + str(t.timeit(100))) 
t = timeit.Timer(method2, setup) 
print('Method 2: ' + str(t.timeit(100))) 

Wyniki:

 
Method 1: 1.25699996948 
Method 2: 1.46600008011 

Jeśli potrzebujesz do iteracji na liście, to korzystanie z for jest w porządku.

+0

Mały dodatek: W python-3.x benchmark pokaże, że mapa zajmuje tylko ułamek milisekundy. To dlatego, że zwróci iterator. method2 = 'list (map (itemgetter (1), elements))' renderuje stare zachowanie. –

+0

To powinna być zaakceptowana odpowiedź. –

21

Działa to również:

zip(*elements)[1] 

(ja głównie delegowania to, aby udowodnić sobie, że mam groked zip ...)

Zobacz go w akcji:

>>> help(zip) 

Pomoc dotycząca wbudowanego zipu funkcji w module wbudowany:

błyskawiczny (...)

błyskawiczny (SEQ1 [, SEQ2 [...]]) -> [(SEQ1 [0] SEQ2 [0], ...), (...) ]

Zwraca listę krotek, gdzie każda krotka zawiera element i-th z każdej z sekwencji argumentów. Zwrócona lista jest skrócona o w długości do najkrótszej sekwencji argumentów.

>>> elements = [(1,1,1),(2,3,7),(3,5,10)] 
>>> zip(*elements) 
[(1, 2, 3), (1, 3, 5), (1, 7, 10)] 
>>> zip(*elements)[1] 
(1, 3, 5) 
>>> 

Neat rzecz dowiedziałem dzisiaj: Użyj *list w argumenty, aby utworzyć listę parametrów dla funkcji ...

+2

i użyj '** dict', aby utworzyć argumenty słów kluczowych:' def test (foo = 3, bar = 3): return foo * bar', następnie 'd = {'bar': 9, 'foo' = 12}; test drukowania (** d) ' –

+0

@Wayne Werner: Tak. To wszystko było tylko bierną wiedzą (nieczęsto się z niej korzystam) - ale dobrze jest mieć przypomnienia od czasu do czasu, więc wiesz gdzie/czego szukać ... –

+0

Prawdziwa historia - stwierdzam, że w czymkolwiek często używam wystarczy (Python, vim), zwykle potrzebuję przypomnień o schludnych/fajnych funkcjach, o których zapomniałem, ponieważ nie używam ich * często *. –

9

Znaleziony to jak szukałem w jaki sposób jest najszybszy wyciągnąć drugi element z 2-krotnej listy.Nie to, co chciałem, ale biegł sam test jak pokazano z 3rd metody oraz przetestować metodę ZIP

setup = 'elements = [(1,1) for _ in range(100000)];from operator import itemgetter' 
method1 = '[x[1] for x in elements]' 
method2 = 'map(itemgetter(1), elements)' 
method3 = 'dict(elements).values()' 
method4 = 'zip(*elements)[1]' 

import timeit 
t = timeit.Timer(method1, setup) 
print('Method 1: ' + str(t.timeit(100))) 
t = timeit.Timer(method2, setup) 
print('Method 2: ' + str(t.timeit(100))) 
t = timeit.Timer(method3, setup) 
print('Method 3: ' + str(t.timeit(100))) 
t = timeit.Timer(method4, setup) 
print('Method 4: ' + str(t.timeit(100))) 

Method 1: 0.618785858154 
Method 2: 0.711684942245 
Method 3: 0.298138141632 
Method 4: 1.32586884499 

więc ponad dwa razy szybciej, jeśli masz parę 2 krotny po prostu przekonwertować do dict i przyjmować wartości.

+0

Jest to prawdopodobnie oczywiste, ale chciałbym wspomnieć o 'dict (elements) .values ​​() 'spowoduje jednoelementowy dyktat w przeciwieństwie do spisu lub mapy. Dokładnie tego chciałem (interesowały mnie wyjątkowe akcenty) (+1 i wielkie dzięki za publikowanie), ale inni mogą się zastanawiać, dlaczego dict jest szybszy - nie alokuje pamięci, a jedynie sprawdza przed istniejącym elementem. – Greg0ry

2
map (lambda x:(x[1]),elements) 
+4

Zastanów się nad dodaniem wyjaśnienia. – fedorqui

0

taktowanie dla Python 3,6 ekstrakcji drugi element z listy 2-krotnego.

Dodana została również metoda tablicowa, która jest łatwiejsza do odczytania (ale prawdopodobnie prostsza niż zrozumienie listy).

from operator import itemgetter 
elements = [(1,1) for _ in range(100000)] 

%timeit second = [x[1] for x in elements] 
%timeit second = list(map(itemgetter(1), elements)) 
%timeit second = dict(elements).values() 
%timeit second = list(zip(*elements))[1] 
%timeit second = np.array(elements)[:,1] 

i czasy:

list comprehension: 4.73 ms ± 206 µs per loop 
list(map):   5.3 ms ± 167 µs per loop 
dict:    2.25 ms ± 103 µs per loop 
list(zip)   5.2 ms ± 252 µs per loop 
numpy array:  28.7 ms ± 1.88 ms per loop 

Zauważ, że map() i zip() nie zwróci listę już, stąd wyraźny konwersję.

Powiązane problemy