2010-07-22 2 views

risposta

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

So che potrebbe essere fatto con un FOR ma volevo sapere se c'è un altro modo

C'è un altro modo. È anche possibile farlo con map e itemgetter:

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

Esegue ancora un anello interno e anche se è leggermente più lento rispetto alla lista di comprensione:

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))) 

Risultati:

 
Method 1: 1.25699996948 
Method 2: 1.46600008011 

Se è necessario scorrere su un elenco, utilizzare for va bene.

+0

Una piccola aggiunta: In python-3.x il benchmark mostrerà che la mappa richiede solo una frazione di millisecondo. Questo perché restituirà un iteratore. method2 = 'list (map (itemgetter (1), elements))' rende il vecchio comportamento. –

+0

Questa dovrebbe essere la risposta accettata. –

21

Questo funziona anche:

zip(*elements)[1] 

(sto principalmente questo distacco, per dimostrare a me stesso che ho groked zip ...)

vederlo in azione:

>>> help(zip) 

Guida per funzione integrata nel modulo zip incorporato:

zip (...)

zip (SEQ1 [, seq2 [...]]) -> [(SEQ1 [0], seq2 [0] ...), (...) ]

Restituisce un elenco di tuple, in cui ogni tupla contiene l'elemento i-esimo da ciascuna sequenza di argomenti. L'elenco restituito viene troncato in lunghezza rispetto alla lunghezza della sequenza di argomenti più breve.

>>> 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) 
>>> 

cosa pulita che ho imparato oggi: Usa *list in argomenti per creare una lista di parametri per una funzione ...

+2

e usare '** dict' per creare argomenti di parole chiave:' def test (foo = 3, bar = 3): return foo * bar' then 'd = {'bar': 9, 'foo' = 12}; print test (** d) ' –

+0

@Wayne Werner: Sì. Questa roba era solo una conoscenza passiva (non la uso spesso) - ma è bene essere ricordati ogni tanto per sapere dove/cosa cercare ... –

+0

Storia vera - Trovo che in qualsiasi cosa io uso spesso abbastanza (Python, vim), tendo ad avere bisogno di promemoria per le caratteristiche nette/fantastiche che ho dimenticato perché non li uso * spesso *. –

9

Abbiamo trovato questo come stavo cercando da che parte è il più veloce per tirare il secondo elemento di una lista di 2 tuple.Non quello che volevo, ma sono imbattuto stesso test come mostrato con un terzo metodo più testare il metodo 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 

Così oltre due volte più veloce se si dispone di una coppia di 2 tuple per convertire solo per un dict e prendere i valori.

+0

Questo è probabilmente ovvio ma vorrei menzionare 'dict (elements) .values ​​() 'si tradurrà in un dettato a un elemento anziché nell'elenco di comprahension o mappa. Questo è esattamente quello che volevo (ero interessato a due tupoli unici) (+1 e grande ringraziamento per la pubblicazione) ma altri potrebbero chiedersi perché il dtt sia più veloce: non sta allocando memoria ma solo controllando contro l'elemento esistente. – Greg0ry

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

Considera di aggiungere qualche spiegazione. – fedorqui

0

tempi per Python 3.6 per estrarre il secondo elemento di una 2-tupla.

Inoltre, aggiunto il metodo di matrice numpy, che è più semplice da leggere (ma probabilmente più semplice della comprensione della lista).

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] 

e gli orari:

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 

noti che map() e zip() non restituiscono un elenco più, da qui la conversione esplicita.