2011-10-30 19 views
39

En Python, ¿hay una buena manera de intercalar dos listas de la misma longitud?Intercalación de dos listas en Python

Di que me dieron [1,2,3] y [10,20,30]. Me gustaría transformarlos en [1,10,2,20,3,30].

+0

Te das cuenta de que es 2.2 ahora diez años? No hay razón para seguir usándolo. –

+3

@DanielRoseman: Sí. En este caso, no tengo otra opción. – NPE

+0

No recomendado, pero intente esto: 'it = iter (l1); list ((yield next (it)) or i for i in l2) ' –

Respuesta

59

haber registrado la pregunta, me he dado cuenta de que puedo hacer simplemente lo siguiente:

[val for pair in zip(l1, l2) for val in pair] 

donde l1 y l2 son las dos listas.

+2

funciona solo si l1 y l2 tienen el mismo número de elementos – Emmanuel

+1

@Emmanuel: La pregunta dice" En Python, ¿hay una buena manera de intercalar dos listas? ** de la misma longitud **? " – NPE

+2

Gracias, creo que necesito un par de gafas nuevas. – Emmanuel

1

Me gusta más la solución de aix. aquí es otra manera creo que debería funcionar en 2.2:

>>> x=range(3) 
>>> x 
[0, 1, 2] 
>>> y=range(7,10) 
>>> y 
[7, 8, 9] 
>>> sum(zip(x,y),[]) 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: can only concatenate list (not "tuple") to list 
>>> sum(map(list,zip(x,y)),[]) 
[0, 7, 1, 8, 2, 9] 

y una forma más de:

>>> a=[x,y] 
>>> [a[i][j] for j in range(3) for i in (0,1)] 
[0, 7, 1, 8, 2, 9] 

y:

>>> sum((list(i) for i in zip(x,y)),[]) 
[0, 7, 1, 8, 2, 9] 
5

alternativos:

>>> l1=[1,2,3] 
>>> l2=[10,20,30] 
>>> [y for x in map(None,l1,l2) for y in x if y is not None] 
[1, 10, 2, 20, 3, 30] 

Estos trabajos porque map trabaja en listas en paralelo. Es works the same bajo 2.2. Por sí misma, la None como las llamadas funciones, map produce una lista de tuplas:

>>> map(None,l1,l2,'abcd') 
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')] 

A continuación, sólo aplanar la lista de tuplas.

La ventaja, por supuesto, es map funcionará para cualquier número de listas y funcionará incluso si son diferentes longitudes:

>>> l1=[1,2,3] 
>>> l2=[10,20,30] 
>>> l3=[101,102,103,104] 
>>> [y for x in map(None,l1,l2,l3) for y in x if y in not None] 
[1, 10, 101, 2, 20, 102, 3, 30, 103, 104] 
+1

'si y' filtrará '0' también,' si y no es None' es menos frágil. –

+0

@Jochen Ritzel: ¡Gracias! Estoy de acuerdo contigo. Fijo. Lo escribí con solo músculos enganchados ... –

29

para Python> = 2.3, hay extended slice syntax:

>>> a = [0, 2, 4, 6, 8] 
>>> b = [1, 3, 5, 7, 9] 
>>> c = a + b 
>>> c[::2] = a 
>>> c[1::2] = b 
>>> c 
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 

La línea c = a + b se usa como una manera simple de crear una nueva lista de la longitud exacta (en esta etapa, sus contenidos no son importantes). Las siguientes dos líneas hacen el trabajo real de entrelazado a y b: la primera asigna los elementos de a a todos los índices pares de c; el segundo asigna los elementos de b a todos los índices impares de c.

5

Necesitaba una forma de hacerlo con listas de diferentes tamaños que la respuesta aceptada no aborda.

Mi solución utiliza un generador y su uso se ve un poco más agradable a causa de ella:

def interleave(l1, l2): 
    iter1 = iter(l1) 
    iter2 = iter(l2) 
    while True: 
     try: 
      if iter1 != None: 
       yield next(iter1) 
     except StopIteration: 
      iter1 = None 
     try: 
      if iter2 != None: 
       yield next(iter2) 
     except StopIteration: 
      iter2 = None 
     if iter1 == None and iter2 == None: 
      raise StopIteration() 

y su uso:

>>> a = [1, 2, 3, 4, 5] 
>>> b = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] 
>>> list(interleave(a, b)) 
[1, 'a', 2, 'b', 3, 'c', 4, 'd', 5, 'e', 'f', 'g'] 
>>> list(interleave(b, a)) 
['a', 1, 'b', 2, 'c', 3, 'd', 4, 'e', 5, 'f', 'g'] 
6

Hay varias opciones.

# Given 
a = [1, 2, 3] 
b = [10, 20, 30] 

Puede obtener una lista intercalados con itertools:

import itertools 

list(itertools.chain(*zip(a, b))) 
# [1, 10, 2, 20, 3, 30] 

considerar la instalación de more_itertools - Una biblioteca que se incluye con las implementaciones de interleave, interleave_longest y la roundrobin itertools recipe.

import more_itertools 

list(more_itertools.interleave(a, b)) 
# [1, 10, 2, 20, 3, 30] 

list(more_itertools.roundrobin(a, b)) 
# [1, 10, 2, 20, 3, 30] 

Finalmente, algo interesante, en Python 3:

list(filter(None, ((yield from i) for i in zip(a, b)))) 
# [1, 10, 2, 20, 3, 30] 
0
[el for el in itertools.chain(*itertools.izip_longest([1,2,3], [4,5])) if el is not None] 

Mientras que usted no tiene None que desea mantener