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
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)
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
.
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)]
d1=['one','two','three']
d2=[1,2,3,4,5]
Zip(d1,d2)
<Zip object at 0x05E494B8>
list(Zip(d1,d2))
{'one': 1, 'two': 2, 'three': 3}
Remarque: Python 3.7+
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)
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)))]
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
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)