J'ai deux listes
a = [1,2,3]
b = [9,10]
Je veux combiner (Zip) ces deux listes en une liste c
telle que
c = [(1,9), (2,10), (3, )]
Y at-il une fonction dans la bibliothèque standard en Python pour faire cela?
Ce que vous cherchez, c'est itertools.izip_longest
Dans Python3.x, vous recherchez itertools.Zip_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 vous voulez vraiment vous débarrasser de la None
s, vous pouvez essayer:
>>> for i in (filter(None, pair) for pair in itertools.izip_longest(a,b)): print i
(1, 9)
(2, 10)
(3,)
EDIT 2 : En réponse au commentaire de steveha:
filter(lambda p: p is not None, pair) for pair in itertools.izip_longest(a,b)
Une autre façon est map
:
a = [1, 2, 3]
b = [9, 10]
c = map(None, a, b)
Bien que cela contienne aussi (3, None)
au lieu de (3,)
. Pour ce faire, voici une ligne amusante:
c = (Tuple(y for y in x if y is not None) for x in map(None, a, b))
Il n'est pas trop difficile d'écrire simplement le Python explicite pour effectuer l'opération souhaitée:
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))
Je ne savais pas trop comment vous voudriez gérer la séquence b
étant plus longue que la séquence a
, alors je me contentais de la placer dans None
pour la première valeur du Tuple dans ce cas.
Obtenez un itérateur explicite pour chaque séquence. Exécutez l'itérateur a
en tant que boucle for
tout en utilisant manuellement next(ib)
pour obtenir la valeur suivante de la séquence b
. Si nous obtenons une StopIteration
sur la séquence b
, nous cassons la boucle et ensuite for x in ia:
récupère le reste de la séquence a
; après cela, for y in ib:
ne fera rien car cet itérateur est déjà épuisé. Sinon, si la première boucle for x in ia:
épuise l'itérateur a
, le deuxième for x in ia:
ne fait rien, mais il pourrait rester des valeurs dans la séquence b
et la boucle for y in ib:
les collectera.
Une seule ligne:
c = Zip(a, b) + [(x,) for x in a[len(b):]] + [(x,) for x in b[len(a):]]
Si vous voulez réutiliser ceci:
def mergeUsNicely(a, b):
def tupleMe(val):
return (val,)
return Zip(a, b) + map(tupleMe, a[len(b):]) + map(tupleMe, b[len(a):])