tutorial lenguaje español descargar python

python - lenguaje - Manera pitónica de combinar dos listas de manera alterna?



python wikipedia (16)

Aquí hay un trazador de líneas que lo hace:

list3 = [ item for pair in zip(list1, list2 + [0]) for item in pair][:-1]

Tengo dos listas, la primera de las cuales garantiza que contiene exactamente un elemento más que el segundo . Me gustaría conocer la forma más pitonica de crear una nueva lista cuyos valores de índice par provengan de la primera lista y cuyos valores de índice impar provengan de la segunda lista.

# example inputs list1 = [''f'', ''o'', ''o''] list2 = [''hello'', ''world''] # desired output [''f'', ''hello'', ''o'', ''world'', ''o'']

Esto funciona, pero no es bonito:

list3 = [] while True: try: list3.append(list1.pop(0)) list3.append(list2.pop(0)) except IndexError: break

¿De qué otra manera se puede lograr esto? ¿Cuál es el enfoque más Pythonic?


Aquí hay un trazador de líneas usando listas de comprensión, sin otras bibliotecas:

list3 = [sub[i] for i in range(len(list2)) for sub in [list1, list2]] + [list1[-1]]

Aquí hay otro enfoque, si permite la alteración de su lista inicial1 por efecto secundario:

[list1.insert((i+1)*2-1, list2[i]) for i in range(len(list2))]


Detiene en el más corto:

def interlace(*iters, next = next) -> collections.Iterable: """ interlace(i1, i2, ..., in) -> ( i1-0, i2-0, ..., in-0, i1-1, i2-1, ..., in-1, . . . i1-n, i2-n, ..., in-n, ) """ return map(next, cycle([iter(x) for x in iters]))

Claro, la resolución del próximo / __ siguiente__ método puede ser más rápido.


Esta es una forma de hacerlo rebanando:

>>> list1 = [''f'', ''o'', ''o''] >>> list2 = [''hello'', ''world''] >>> result = [None]*(len(list1)+len(list2)) >>> result[::2] = list1 >>> result[1::2] = list2 >>> result [''f'', ''hello'', ''o'', ''world'', ''o'']


Esta se basa en la contribución anterior de Carlos Valiente con una opción para alternar grupos de múltiples elementos y asegurarse de que todos los elementos estén presentes en el resultado:

A=["a","b","c","d"] B=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16] def cyclemix(xs, ys, n=1): for p in range(0,int((len(ys)+len(xs))/n)): for g in range(0,min(len(ys),n)): yield ys[0] ys.append(ys.pop(0)) for g in range(0,min(len(xs),n)): yield xs[0] xs.append(xs.pop(0)) print [x for x in cyclemix(A, B, 3)]

Esto entrelazará las listas A y B por grupos de 3 valores cada uno:

[''a'', ''b'', ''c'', 1, 2, 3, ''d'', ''a'', ''b'', 4, 5, 6, ''c'', ''d'', ''a'', 7, 8, 9, ''b'', ''c'', ''d'', 10, 11, 12, ''a'', ''b'', ''c'', 13, 14, 15]


Esto debería hacer lo que quieras:

>>> iters = [iter(list1), iter(list2)] >>> print list(it.next() for it in itertools.cycle(iters)) [''f'', ''hello'', ''o'', ''world'', ''o'']


Esto es desagradable pero funciona sin importar el tamaño de las listas:

list3 = [element for element in list(itertools.chain.from_iterable([val for val in itertools.izip_longest(list1, list2)])) if element != None]


Haría lo simple:

chain.from_iterable( izip( list1, list2 ) )

Aparecerá un iterador sin crear ninguna necesidad de almacenamiento adicional.


Hay una receta para esto en la documentación de itertools :

from itertools import cycle, islice def roundrobin(*iterables): "roundrobin(''ABC'', ''D'', ''EF'') --> A D E B F C" # Recipe credited to George Sakkis pending = len(iterables) nexts = cycle(iter(it).next for it in iterables) while pending: try: for next in nexts: yield next() except StopIteration: pending -= 1 nexts = cycle(islice(nexts, pending))


Múltiples frases inspiradas por respuestas a otra pregunta :

import itertools list(itertools.chain.from_iterable(itertools.izip_longest(list1, list2, fillvalue=object)))[:-1] [i for l in itertools.izip_longest(list1, list2, fillvalue=object) for i in l if i is not object] [item for sublist in map(None, list1, list2) for item in sublist][:-1]


Mi toma:

a = "hlowrd" b = "el ol" def func(xs, ys): ys = iter(ys) for x in xs: yield x yield ys.next() print [x for x in func(a, b)]


Sé que las preguntas se refieren a dos listas, una de las cuales tiene un ítem más que la otra, pero pensé que podría poner esto para otros que puedan encontrar esta pregunta.

Aquí está la solución de Duncan adaptada para trabajar con dos listas de diferentes tamaños.

list1 = [''f'', ''o'', ''o'', ''b'', ''a'', ''r''] list2 = [''hello'', ''world''] num = min(len(list1), len(list2)) result = [None]*(num*2) result[::2] = list1[:num] result[1::2] = list2[:num] result.extend(list1[num:]) result.extend(list2[num:]) result

Esto produce:

[''f'', ''hello'', ''o'', ''world'', ''o'', ''b'', ''a'', ''r'']


Sin itertools y suponiendo que l1 es 1 elemento más que l2:

>>> sum(zip(l1, l2+[0]), ())[:-1] (''f'', ''hello'', ''o'', ''world'', ''o'')

Usando itertools y asumiendo que las listas no contengan None:

>>> filter(None, sum(itertools.izip_longest(l1, l2), ())) (''f'', ''hello'', ''o'', ''world'', ''o'')


Soy demasiado viejo para estar abajo con la lista de comprensiones, entonces:

import operator list3 = reduce(operator.add, zip(list1, list2))


def combine(list1, list2): lst = [] len1 = len(list1) len2 = len(list2) for index in range( max(len1, len2) ): if index+1 <= len1: lst += [list1[index]] if index+1 <= len2: lst += [list2[index]] return lst


import itertools print [x for x in itertools.chain.from_iterable(itertools.izip_longest(list1,list2)) if x]

Creo que esta es la forma más pitonica de hacerlo.