2012-07-03 14 views

risposta

31

Quello che cercate è itertools.izip_longest

>>> a = [1,2,3] 
>>> b = [9,10] 
>>> for i in itertools.izip_longest(a,b): print i 
... 
(1, 9) 
(2, 10) 
(3, None) 

EDIT 1: Se davvero si vuole sbarazzarsi dei None s, allora si potrebbe provare:

>>> for i in (filter(None, pair) for pair in itertools.izip_longest(a,b)): print i 
(1, 9) 
(2, 10) 
(3,) 

EDIT 2: In risposta al commento di steveha:

filter(lambda p: p is not None, pair) for pair in itertools.izip_longest(a,b) 
+7

Usa 'itertools.zip_longest' per Python 3.5+. –

7

Un altro modo è map:

a = [1, 2, 3] 
b = [9, 10] 
c = map(None, a, b) 

Anche se questo sarà anche contenere (3, None) invece di (3,). Per fare questo, ecco una linea di divertente:

c = (tuple(y for y in x if y is not None) for x in map(None, a, b)) 
+0

'x se Nessuno non è in x altra tupla (y per y in x se y non è None)'. Il 'x se None not in x' è ridondante qui, come il' else' si prende cura di esso. Nel peggiore dei casi, il 'else' restituirebbe una tupla vuota. Inoltre, se c'è un 'None' in qualsiasi tupla, il' if' ucciderebbe quella tupla e la passerebbe al 'else' – inspectorG4dget

+0

@ inspectorG4dget: Grazie.Ma ora non è così divertente: D – Ryan

+0

Funziona bene in Python 2.7, ma non in 3.5. Per 3.5 usa 'itertools.zip_longest'. –

2

Non è troppo difficile basta scrivere Python esplicito di fare l'operazione desiderata:

def izip_short(a, b): 
    ia = iter(a) 
    ib = iter(b) 
    for x in ia: 
     try: 
      y = next(ib) 
      yield (x, y) 
     except StopIteration: 
      yield (x,) 
      break 
    for x in ia: 
     yield (x,) 
    for y in ib: 
     yield (None, y) 

a = [1, 2, 3] 
b = [9, 10] 
list(izip_short(a, b)) 
list(izip_short(b, a)) 

non ero sicuro di come si vorrebbe gestire la sequenza b è più lunga della sequenza a, quindi inserisco semplicemente un None per il primo valore nella tupla in quel caso.

Ottieni un iteratore esplicito per ciascuna sequenza. Eseguire l'iteratore a come ciclo for, mentre manualmente utilizzando next(ib) per ottenere il valore successivo dalla sequenza b. Se otteniamo un StopIteration nella sequenza b, interrompiamo il ciclo e quindi for x in ia: ottiene il resto della sequenza a; dopo di che for y in ib: non farà nulla perché l'iteratore è già esaurito. In alternativa, se il primo ciclo for x in ia: esaurisce l'iteratore a, il secondo for x in ia: non fa altro che valori nella sequenza b e il ciclo for y in ib: li raccoglie.

1

linea singola:

c = zip(a, b) + [(x,) for x in a[len(b):]] + [(x,) for x in b[len(a):]]

Se si desidera riutilizzare questo:

def mergeUsNicely(a, b): 
    def tupleMe(val): 
     return (val,) 
    return zip(a, b) + map(tupleMe, a[len(b):]) + map(tupleMe, b[len(a):]) 
Problemi correlati