2016-03-04 14 views
7

Come faccio a ciclo attraverso i miei 2 liste in modo da poter usareCrea nuovo elenco prendendo prima voce dalla prima lista, e l'ultimo elemento dalla seconda lista

a=[1,2,3,8,12] 
b=[2,6,4,5,6] 

per ottenere

[1,6,2,5,3,8,6,12,2] 

O utilizzare

d=[a,b,c,d] 
e=[w,x,y,z] 

per ottenere

[a,z,b,y,c,x,d,w] 

(1 ° elemento dal 1 ° lista, ultimo elemento dal 2 lista)
(2 ° elemento dal 1 ° lista, 2 ° all'ultimo elemento dalla seconda lista)

+0

Quale parte stai avendo difficoltà con? –

risposta

11
[value for pair in zip(a, b[::-1]) for value in pair] 
5

È possibile comprimere la prima lista con il rovescio della seconda (utilizzando itertools.izip_longest) poi unirsi alle colonne utilizzando itertools.chain:

>>> d=['a','b','c','d'] 
>>> e=['w','x','y','z'] 
>>> 
>>> from itertools import chain, zip_longest # in python 2 use izip_longest 
>>> 
>>> list(chain(*izip_longest(d, e[::-1]))) 
['a', 'z', 'b', 'y', 'c', 'x', 'd', 'w'] 

il vantaggio di utilizzare zip_longest() è che ci vuole un argomento fillvalue che verrà passato a riempire gli elementi omessi quando la lunghezza delle tue liste non sono uguali.

Se si è sicuri che la lunghezza degli elenchi sia uguale è meglio utilizzare la funzione integrata zip().

>>> d=['a','b'] 
>>> e=['w','x','y','z'] 
>>> list(chain(*izip_longest(d, e[::-1], fillvalue=''))) 
['a', 'z', 'b', 'y', '', 'x', '', 'w'] 

Altro modo divinatorio suggerito da @ Jon Clements:

list(chain.from_iterable(zip_longest(d, reversed(e)))) 
+0

È considerata una forma migliore usare 'chain.from_iterable (iterable)' invece di 'chain (* iterable)' ... e se si volesse evitare di creare una nuova lista, invece di 'e [:: - 1]' si può usare 'invertito (e)' quindi tutto sommato: 'lista (catena.from_iterable (zip_longest (d, reverseed (e)))) ' –

+0

Forse il metodo che utilizzerei è prendere la ricetta' roundrobin' itertools e fornirgli 'd' e' reverseed (e) 'come input - che Gestiremo liste di lunghezza piacevolmente variabili (senza preoccuparci dei fillvalues) e scaleremo ad un numero arbitrario di iterabili come input –

+0

@JonClements Sì, usare 'reverse()' è un'idea migliore ma penso che si usi 'roundrobin' (sebbene sia il modo pitodico) è eccessivo in questo caso. – Kasramvd

0

Beh, ho fatto alcuni test per python2:

import time 
from operator import itemgetter 
from itertools import chain, izip_longest 

a = [1, 2, 3, 8, 12] 
b = [2, 6, 4, 5, 6] 

print "Using value and zip" 
starttime = time.time() 
c = [value for pair in zip(a, b[::-1]) for value in pair] 
elapsed = time.time() - starttime 
print c 
print elapsed 

print "Using chain and izip" 
starttime = time.time() 
c = list(chain(*izip_longest(a, b[::-1]))) 
elapsed = time.time() - starttime 
print c 
print elapsed 

print "Using itemgetter" 
c = [] 
starttime = time.time() 
for i in xrange(0, len(a)): 
    c.append(itemgetter(i)(a)) 
    c.append(itemgetter(len(b)-i-1)(b)) 
elapsed = time.time() - starttime 
print c 
print elapsed 

uscita:

Using value and zip 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 
1.59740447998e-05 
Using chain and izip 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 
3.2901763916e-05 
Using itemgetter 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 
1.4066696167e-05 

A volte il primo metodo è più veloce e talvolta il terzo.

Quelli sono i risultati per gli elenchi La lunghezza delle = 1000:

Using value and zip 
0.000767946243286 
Using chain and izip 
0.000431060791016 
Using itemgetter 
0.00203609466553 

Come si può vedere il secondo metodo migliora per gli elenchi più lunghi.

0

ne dite di questo:

a=[1,2,3,8,12] 
b=[2,6,4,5,6] 
>>> a1 = list(map(lambda x: a1.extend([x,0]), a)) 
[None, None, None, None, None] 
>>> a1 
[1, 0, 2, 0, 3, 0, 8, 0, 12, 0] 
>>> b1 = list(map(lambda x: b1.extend([0,x]), b[::-1])) 
[None, None, None, None, None] 
>>> b1 
[0, 6, 0, 5, 0, 4, 0, 6, 0, 2] 
>>> c = [x+y for x,y in zip(a1,b1)] 
>>> c 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 

Se a e b sono con diverse lunghezze, quindi:

>>> c = [x+y for x,y in izip_longest(a1,b1)] #you choose your fillvalue. 
Problemi correlati