2011-12-04 10 views
40

Qual è il modo più veloce ed elegante di eseguire elenchi di elenchi da due elenchi?Zip con output di lista invece di tupla

devo

In [1]: a=[1,2,3,4,5,6] 

In [2]: b=[7,8,9,10,11,12] 

In [3]: zip(a,b) 
Out[3]: [(1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12)] 

e mi piacerebbe avere

In [3]: some_method(a,b) 
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]] 

Stavo pensando di usare la mappa, invece di zip, ma non so se c'è qualche metodo libreria standard mettere come prima discussione.

Posso sfidare la mia funzione e utilizzare la mappa, la mia domanda è se è già stato implementato qualcosa. No è anche una risposta.

+1

Bene, hai davvero ** bisogno di ** elenchi? Che cosa hai intenzione di fare con i risultati? –

+7

Un esempio potrebbe essere sklearn, in cui molte volte i dati devono essere organizzati in questo modo. –

risposta

52

Se si zippare più di 2 liste (o anche solo 2, è per questo), un modo leggibile potrebbe essere:

[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])] 

Ciò usa list comprehension e converte ogni elemento della lista (tuple) nelle liste.

3

io in genere non mi piace usare lambda, ma ...

>>> a = [1, 2, 3, 4, 5] 
>>> b = [6, 7, 8, 9, 10] 
>>> c = lambda a, b: [list(c) for c in zip(a, b)] 
>>> c(a, b) 
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]] 

Se avete bisogno della velocità extra, mappa è leggermente più veloce:

>>> d = lambda a, b: map(list, zip(a, b)) 
>>> d(a, b) 
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]] 

Tuttavia, mappa è considerato unpythonic e dovrebbe essere usato solo per la regolazione delle prestazioni.

+3

Cosa aggiunge 'lambda' qui? Si può semplicemente scrivere l'espressione invece di chiamare una funzione (in realtà non è complicata), e anche se si vuole una funzione per essa, può essere definita in modo indolore in due righe (una se la chiave di ritorno è rotta o se si è pazzi) . 'map' d'altra parte è perfettamente a posto se il primo argomento sarebbe una funzione semplice (al contrario di un' lambda'). – delnan

+1

Beh, ha chiesto una funzione. Ma sono d'accordo, probabilmente meglio solo per pagare la linea in più. Per quanto riguarda la mappa, credo che la comprensione delle liste sia quasi sempre più chiara. –

+1

Consiglierei 'map' su' lambda'. quindi 'map (lista, zip (a, b))'. La comprensione delle liste può essere un po 'più chiara, ma la mappa dovrebbe essere più veloce (non testata) – inspectorG4dget

1

Che ne dici di questo?

>>> def list_(*args): return list(args) 

>>> map(list_, range(5), range(9,4,-1)) 
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]] 

O ancora meglio:

>>> def zip_(*args): return map(list_, *args) 
>>> zip_(range(5), range(9,4,-1)) 
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]] 
+0

Questa mi sembra una risposta migliore rispetto al resto dato che qui stiamo riducendo un passaggio non facendo un zip e creando direttamente un elenco. Impressionante –

12

amo l'eleganza della funzione di cerniera, ma utilizzando la funzione di itemgetter() nel modulo operatore sembra essere molto più veloce. Ho scritto un semplice script per testare questo:

import time 
from operator import itemgetter 

list1 = list() 
list2 = list() 
origlist = list() 
for i in range (1,5000000): 
     t = (i, 2*i) 
     origlist.append(t) 

print "Using zip" 
starttime = time.time() 
list1, list2 = map(list, zip(*origlist)) 
elapsed = time.time()-starttime 
print elapsed 

print "Using itemgetter" 
starttime = time.time() 
list1 = map(itemgetter(0),origlist) 
list2 = map(itemgetter(1),origlist) 
elapsed = time.time()-starttime 
print elapsed 

mi aspettavo zip per essere più veloce, ma il metodo itemgetter vince da un colpo lungo:

Using zip 
6.1550450325 
Using itemgetter 
0.768098831177 
+2

Questa è una trasposizione di ciò che l'OP sta tentando di fare. Potresti aggiornare il tuo post per riflettere questo? I.e., OP sta convertendo due liste per elencare o un numero arbitrario di coppie. Stai convertendo un numero arbitrario di coppie in una coppia di liste. –

+0

Con quale versione python viene misurata questa? – Moberg

+0

Non ricordo, era più di due anni fa, ma molto probabilmente 2.6 o 2.7. Immagino che tu possa copiare il codice e provarlo sulla tua versione/piattaforma. – kslnet

12

È quasi avuto la risposta da soli. Non utilizzare map anziché zip. Utilizzare mapEzip.

È possibile utilizzare carta con zip per un elegante approccio, funzionale:

map(list, zip(a, b)) 

zip restituisce una lista di tuple. map(list, [...]) chiama list su ogni tupla nell'elenco.

0

La comprensione delle liste sarebbe una soluzione molto semplice, immagino.

a=[1,2,3,4,5,6] 

b=[7,8,9,10,11,12] 

x = [[i, j] for i, j in zip(a,b)] 

print(x) 

output : [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]] 
Problemi correlati