2012-07-03 9 views

Respuesta

31

Lo que buscan es 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: Si realmente quiere deshacerse de las None s, entonces usted podría intentar:

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

EDIT 2: En respuesta al comentario de steveha:

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

Use 'itertools.zip_longest' para Python 3.5 +. –

7

Otra forma es map:

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

A pesar de que también lo hará en lugar de contener (3, None)(3,). Para hacer eso, he aquí una línea de la diversión:

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

'x if None no en x else tuple (y para y en x si y no es None)'. El 'x if None no en x' es redundante aquí, ya que el' else' se encarga de ello. En el peor de los casos, el 'else' devolvería una tupla vacía. Además, si hay un 'None' en cualquier tupla, el' if' mataría esa tupla y la pasaría al 'else' – inspectorG4dget

+0

@ inspectorG4dget: Gracias.Pero ahora no es tan divertido: D – Ryan

+0

Funciona bien en Python 2.7, pero no en 3.5. Para 3.5 usa 'itertools.zip_longest'. –

2

No es demasiado difícil simplemente escribir el pitón explícita a realizar la operación deseada:

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

yo no estaba seguro de cómo le gustaría que para manejar la secuencia b es más larga que la secuencia a, así que simplemente rellene un None para el primer valor en la tupla en ese caso.

Obtenga un iterador explícito para cada secuencia. Ejecute el iterador a como un bucle for, mientras usa manualmente next(ib) para obtener el siguiente valor de la secuencia b. Si obtenemos un StopIteration en la secuencia b, rompemos el ciclo y luego for x in ia: obtiene el resto de la secuencia a; después de eso for y in ib: no hará nada porque ese iterador ya está agotado. Alternativamente, si el primer bucle for x in ia: agota el iterador a, el segundo for x in ia: no hace nada pero puede haber valores en la secuencia b y el bucle for y in ib: los recoge.

1

Una sola línea:

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

Si desea volver a utilizar esto:

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