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]
.
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]
.
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.
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]
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]
'si y' filtrará '0' también,' si y no es None' es menos frágil. –
@Jochen Ritzel: ¡Gracias! Estoy de acuerdo contigo. Fijo. Lo escribí con solo músculos enganchados ... –
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
.
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']
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]
[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
Te das cuenta de que es 2.2 ahora diez años? No hay razón para seguir usándolo. –
@DanielRoseman: Sí. En este caso, no tengo otra opción. – NPE
No recomendado, pero intente esto: 'it = iter (l1); list ((yield next (it)) or i for i in l2) ' –