Existe-t-il une fonction de type zip qui se remplit sur la plus grande longueur en Python?


170

Existe-t-il une fonction intégrée qui fonctionne comme zip()mais qui remplira les résultats de sorte que la longueur de la liste résultante soit la longueur de l' entrée la plus longue plutôt que celle de l' entrée la plus courte ?

>>> a = ['a1']
>>> b = ['b1', 'b2', 'b3']
>>> c = ['c1', 'c2']

>>> zip(a, b, c)
[('a1', 'b1', 'c1')]

>>> What command goes here?
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

Réponses:


243

Dans Python 3, vous pouvez utiliser itertools.zip_longest

>>> list(itertools.zip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

Vous pouvez ajouter une valeur différente de celle Noneen utilisant le fillvalueparamètre:

>>> list(itertools.zip_longest(a, b, c, fillvalue='foo'))
[('a1', 'b1', 'c1'), ('foo', 'b2', 'c2'), ('foo', 'b3', 'foo')]

Avec Python 2, vous pouvez soit utiliser itertools.izip_longest(Python 2.6+), soit utiliser mapavec None. C'est une fonctionnalité peu connue demap (mais mapmodifiée dans Python 3.x, donc cela ne fonctionne que dans Python 2.x).

>>> map(None, a, b, c)
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

3
N'avons-nous pas de solution Python 3 non itertools?
PascalVKooten

3
@PascalvKooten ce n'est pas obligatoire. itertoolsest de toute façon un module C intégré.
Antti Haapala

82

Pour Python 2.6x, utilisez les itertoolsmodules izip_longest.

Pour Python 3, utilisez à la zip_longestplace (pas de début i).

>>> list(itertools.izip_longest(a, b, c))
[('a1', 'b1', 'c1'), (None, 'b2', 'c2'), (None, 'b3', None)]

8
Si vous souhaitez rendre votre code compatible python 2 et python 3, vous pouvez utiliser à la six.moves.zip_longestplace.
Gamrix

5

solution Python 3 non itertools:

def zip_longest(*lists):
    def g(l):
        for item in l:
            yield item
        while True:
            yield None
    gens = [g(l) for l in lists]    
    for _ in range(max(map(len, lists))):
        yield tuple(next(g) for g in gens)

2

non itertools Ma solution Python 2:

if len(list1) < len(list2):
    list1.extend([None] * (len(list2) - len(list1)))
else:
    list2.extend([None] * (len(list1) - len(list2)))

0

J'utilise un tableau 2D mais le concept est le même en utilisant python 2.x:

if len(set([len(p) for p in printer])) > 1:
    printer = [column+['']*(max([len(p) for p in printer])-len(column)) for column in printer]

2
Veuillez ajouter une explication sur la raison pour laquelle ce code fonctionne. Ou pourquoi c'est la bonne réponse
Suit Boy Apps
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.