En Python, existe-t-il un bon moyen d'entrelacer deux listes de même longueur ?
Dites que je suis donné [1,2,3]
et [10,20,30]
. J'aimerais les transformer en [1,10,2,20,3,30]
.
En Python, existe-t-il un bon moyen d'entrelacer deux listes de même longueur ?
Dites que je suis donné [1,2,3]
et [10,20,30]
. J'aimerais les transformer en [1,10,2,20,3,30]
.
@Emmanuel : La question est la suivante : "En Python, existe-t-il un bon moyen d'entrelacer deux listes ? de la même longueur ?"
Si vous souhaitez ajouter un pad à la liste la plus longue, utilisez izip_longest
pour python2 et zip_longest
pour python3 ` [val for pair in itertools.zip_longest(l1, l2) for val in pair]
les résultats avec ['a', 'b', 'a', 'b', 'a', 'b', None, 'b', None, 'b', None, 'b']
Pour Python>=2.3, il y a syntaxe étendue de la tranche :
>>> 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 ligne c = a + b
est utilisé comme un moyen simple de créer une nouvelle liste ayant exactement la bonne longueur (à ce stade, son contenu n'est pas important). Les deux lignes suivantes effectuent le travail d'entrelacement proprement dit a
et b
le premier attribue les éléments de a
à tous les index pairs de c
; la seconde assigne les éléments de b
à tous les index impairs de c
.
Étant donné que
a = [1, 2, 3]
b = [10, 20, 30]
c = [100, 200, 300, 999]
Code
En supposant des listes de longueur égale, vous pouvez obtenir une liste entrelacée avec itertools.chain
et zip
:
import itertools
list(itertools.chain(*zip(a, b)))
# [1, 10, 2, 20, 3, 30]
Alternatives
Plus généralement avec des listes inégales, utilisez zip_longest
(recommandé) :
[x for x in itertools.chain(*itertools.zip_longest(a, c)) if x is not None]
# [1, 100, 2, 200, 3, 300, 999]
De nombreuses listes peuvent être imbriquées en toute sécurité :
[x for x in itertools.chain(*itertools.zip_longest(a, b, c)) if x is not None]
# [1, 10, 100, 2, 20, 200, 3, 30, 300, 999]
_more_itertools
_ +
Une bibliothèque qui est livrée avec le roundrobin
recette itertools, interleave
et interleave_longest
.
import more_itertools
list(more_itertools.roundrobin(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave(a, b))
# [1, 10, 2, 20, 3, 30]
list(more_itertools.interleave_longest(a, c))
# [1, 100, 2, 200, 3, 300, 999]
yield from
Enfin, pour quelque chose d'intéressant en Python 3 (bien que non recommandé) :
list(filter(None, ((yield from x) for x in zip(a, b))))
# [1, 10, 2, 20, 3, 30]
list([(yield from x) for x in zip(a, b)])
# [1, 10, 2, 20, 3, 30]
<sup>+ </sup>Installer en utilisant <code>pip install more_itertools</code>
J'avais besoin d'un moyen de faire cela avec des listes de tailles différentes, ce que la réponse acceptée ne permet pas de faire.
Ma solution utilise un générateur et son utilisation est un peu plus agréable grâce à lui :
def interleave(l1, l2):
iter1 = iter(l1)
iter2 = iter(l2)
while True:
try:
if iter1 is not None:
yield next(iter1)
except StopIteration:
iter1 = None
try:
if iter2 is not None:
yield next(iter2)
except StopIteration:
iter2 = None
if iter1 is None and iter2 is None:
raise StopIteration()
Et son utilisation :
>>> 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']
Le site roundrobin
recette du itertools
module est une extension plus générale de ce principe.
Alternatif :
>>> 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]
Cela fonctionne parce que carte travaille sur des listes en parallèle. Il fonctionne de la même manière sous 2.2. En soi, avec None
comme fonctions appelées, map
produit une liste de tuples :
>>> map(None,l1,l2,'abcd')
[(1, 10, 'a'), (2, 20, 'b'), (3, 30, 'c'), (None, None, 'd')]
Ensuite, il suffit d'aplatir la liste des tuples.
L'avantage, bien sûr, est map
fonctionnera pour n'importe quel nombre de listes et fonctionnera même si elles sont de longueurs différentes :
>>> 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]
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
0 votes
Non recommandé, mais essayez ceci :
it = iter(l1); list((yield next(it)) or i for i in l2)
0 votes
Cela répond-il à votre question ? Méthode pythonique pour combiner deux listes de manière alternée ?