web-dev-qa-db-fra.com

Comment compresser deux listes de tailles différentes?

Je veux compresser deux listes de longueurs différentes 

par exemple

A = [1,2,3,4,5,6,7,8,9]
B = ["A","B","C"]

et j'attends ceci

[(1, 'A'), (2, 'B'), (3, 'C'), (4, 'A'), (5, 'B'), (6, 'C'), (7, 'A'), (8, 'B'), (9, 'C')]

Mais le Zip intégré ne sera pas répété pour s'associer à la liste avec une taille plus grande . Existe-t-il un moyen interne de réaliser cela? Merci

voici mon code

idx = 0
Zip_list = []
for value in larger:
    Zip_list.append((value,smaller[idx]))
    idx += 1
    if idx == len(smaller):
        idx = 0
28
user2131116

Vous pouvez utiliser itertools.cycle :

Créez un itérateur en renvoyant des éléments de l'iterable et en enregistrant une copie. Lorsque l'itérable est épuisé, renvoyez les éléments de la copie enregistrée. Répète indéfiniment. 

Exemple:

A = [1,2,3,4,5,6,7,8,9]
B = ["A","B","C"]

from itertools import cycle
Zip_list = Zip(A, cycle(B)) if len(A) > len(B) else Zip(cycle(A), B)
56
sloth

Essaye ça.

A = [1,2,3,4,5,6,7,8,9]
B = ["A","B","C"]
Z = []
for i, a in enumerate(A):
    Z.append((a, B[i % len(B)]))

Assurez-vous simplement que la liste la plus longue est dans A.

7
Eser Aygün

Et de nos jours avec list comprehentions

[(i, B[i % 3 - 1]) for i in A]

Ou si les éléments de A ne sont pas séquentiels et ne s’inquiètent pas de la longueur des listes

[(j, B[i % len(B)]) for i, j in enumerate(A)] if len(A) >= len(B) else \
[(A[i % len(A)], j) for i, j in enumerate(B)]
0
dimitris_ps
d1=['one','two','three']
d2=[1,2,3,4,5]

Zip *: français

Zip(d1,d2)
<Zip object at 0x05E494B8>

liste de Zip

list(Zip(d1,d2))

dictionnaire de liste de Zip

{'one': 1, 'two': 2, 'three': 3}

Remarque: Python 3.7+

0
Gajendra D Ambi

Solution pour un nombre arbitraire d'itérables, et vous ne savez pas lequel est le plus long (autorisant également une valeur par défaut pour tout itérable vide)

from itertools import cycle, Zip_longest

def Zip_cycle(*iterables, empty_default=None):
    cycles = [cycle(i) for i in iterables]
    for _ in Zip_longest(*iterables):
        yield Tuple(next(i, empty_default) for i in cycles)

for i in Zip_cycle(range(2), range(5), ['a', 'b', 'c'], []):
    print(i)

Les sorties:

(0, 0, 'a', None)
(1, 1, 'b', None)
(0, 2, 'c', None)
(1, 3, 'a', None)
(0, 4, 'b', None)
0
Dane White

symétrique, pas de conditional one liner 

[*Zip(A*(len(B)//len(A) + 1), B*(len(A)//len(B) + 1))]

qui répond strictement 'Comment compresser deux différemment tailles de listes?'

a besoin d’un patch pour que les listes de tailles égales soient générales:

[*(Zip(A, B) if len(A) == len(B)
         else Zip(A*(len(B)//len(A) + 1),
                  B*(len(A)//len(B) + 1)))]
0
f5r5e5d

Pour une version qui fonctionne avec n'importe quel nombre fini d'itérables potentiellement infinis dans n'importe quel ordre:

from itertools import cycle, tee, Zip_longest

def cyclical_Zip(*iterables):
    iterables_1, iterables_2 = Zip(*map(tee, iterables))  # Allow proper iteration of iterators

    for _, x in Zip(
            Zip_longest(*iterables_1),      # Limit             by the length of the longest iterable
            Zip(*map(cycle, iterables_2))): #       the cycling
        yield x

assert list(cyclical_Zip([1, 2, 3], 'abcd', 'xy')) == [(1, 'a', 'x'), (2, 'b', 'y'), (3, 'c', 'x'), (1, 'd', 'y')]  # An example and test case
0
Solomon Ucko

Il y a probablement une meilleure solution, mais vous pouvez créer une fonction qui répète votre liste à la longueur souhaitée.

def repeatlist(l,i):
    '''give a list and a total length'''
    while len(l) < i:
        l += l
    while len(l) > i:
        l.pop()

Alors fais 

repeatlist(B,len(A))
Zip_list = Zip(A,B)
0
James Robinson