Listes Zip en Python


151

J'essaye d'apprendre comment «compresser» des listes. À cette fin, j'ai un programme, où à un moment donné, je fais ce qui suit:

x1, x2, x3 = stuff.calculations(withdataa)

Cela me donne trois listes, x1, x2et x3, chacun, par exemple, la taille 20.

Maintenant oui:

zipall = zip(x1, x2, x3)

Cependant, quand je fais:

print "len of zipall %s" % len(zipall)

J'en ai 20, ce qui n'est pas ce à quoi je m'attendais. J'en attendais trois. Je pense que je fais quelque chose de fondamentalement mal.


4
Qu'espérez-vous zipfaire exactement ? Pourquoi devriez-vous avoir trois listes - à quoi ressembleraient-elles?
Daniel Roseman

zip renvoie une liste de tuples.
Démo du

Réponses:


225

Lorsque vous zip()regroupez trois listes contenant chacune 20 éléments, le résultat a vingt éléments. Chaque élément est un triplet.

Voir par vous-même:

In [1]: a = b = c = range(20)

In [2]: zip(a, b, c)
Out[2]: 
[(0, 0, 0),
 (1, 1, 1),
 ...
 (17, 17, 17),
 (18, 18, 18),
 (19, 19, 19)]

Pour savoir combien d'éléments chaque tuple contient, vous pouvez examiner la longueur du premier élément:

In [3]: result = zip(a, b, c)

In [4]: len(result[0])
Out[4]: 3

Bien sûr, cela ne fonctionnera pas si les listes étaient vides au départ.


1
len (result [0]) ne fonctionnera pas. L'objet 'zip' n'est pas en indice
GilbertS

2
@GilbertS dans Python 2 a ziprenvoyé une liste. Dans Python 3 c'est un itérateur
Tomerikoo

63

zip prend un tas de listes de likes

a: a1 a2 a3 a4 a5 a6 a7...
b: b1 b2 b3 b4 b5 b6 b7...
c: c1 c2 c3 c4 c5 c6 c7...

et les "zips" dans une liste dont les entrées sont 3-tuples (ai, bi, ci). Imaginez dessiner une fermeture à glissière horizontalement de gauche à droite.



36

En Python 2.7, cela aurait pu fonctionner correctement:

>>> a = b = c = range(20)
>>> zip(a, b, c)

Mais dans Python 3.4, cela devrait être (sinon, le résultat sera quelque chose comme <zip object at 0x00000256124E7DC8>):

>>> a = b = c = range(20)
>>> list(zip(a, b, c))

28

zip crée une nouvelle liste, remplie de tuples contenant des éléments des arguments itérables:

>>> zip ([1,2],[3,4])
[(1,3), (2,4)]

J'attends ce que vous essayez de créer un tuple où chaque élément est une liste.


14

Source: Mon article de blog (meilleur formatage)

Exemple

numbers = [1,2,3]
letters = 'abcd'

zip(numbers, letters)
# [(1, 'a'), (2, 'b'), (3, 'c')]

Contribution

Zéro ou plusieurs itérables [1] (ex. Liste, chaîne, tuple, dictionnaire)

Sortie (liste)

1er tuple = (élément_1 des nombres, élément_1 des lettres)

2ème tuple = (nombres e_2, lettres e_2)

n-ième tuple = (e_n nombres, e_n lettres)

  1. Liste de n tuples: n est la longueur de l'argument le plus court (entrée)
    • len (nombres) == 3 <len (lettres) == 4 → court = 3 → retourne 3 tuples
  2. Length each tuple = # of args (tuple prend un élément de chaque arg)
    • args = (nombres, lettres); len (args) == 2 → tuple avec 2 éléments
  3. ith tuple = (element_i arg1, element_i arg2…, element_i arg n)

Cas de bord

1) Chaîne vide: len (str) = 0 = pas de tuples

2) Chaîne unique: len (str) == 2 tuples avec len (args) == 1 élément (s)

zip()
# []
zip('')
# []
zip('hi')
# [('h',), ('i',)]

Zip en action!

1. Construisez un dictionnaire [2] à partir de deux listes

keys = ["drink","band","food"]
values = ["La Croix", "Daft Punk", "Sushi"]

my_favorite = dict( zip(keys, values) )

my_favorite["drink"]
# 'La Croix'

my_faves = dict()
for i in range(len(keys)):
    my_faves[keys[i]] = values[i]
  • zip est une solution élégante, claire et concise

2. Imprimer des colonnes dans un tableau

"*" [3] est appelé "déballage": f(*[arg1,arg2,arg3]) == f(arg1, arg2, arg3)

student_grades = [
[   'Morty'  ,  1   ,  "B"  ],
[   'Rick'   ,  4   ,  "A"  ],
[   'Jerry'  ,  3   ,  "M"  ],
[  'Kramer'  ,  0   ,  "F"  ],
]

row_1 = student_grades[0]
print row_1
# ['Morty', 1, 'B']

columns = zip(*student_grades)
names = columns[0]
print names
# ('Morty', 'Rick', 'Jerry', 'Kramer')

Crédit supplémentaire: décompression

zip(*args) est appelé «décompression» car il a pour effet inverse zip

numbers = (1,2,3)
letters = ('a','b','c')

zipped = zip(numbers, letters)
print zipped
# [(1, 'a'), (2, 'b'), (3, 'c')]

unzipped = zip(*zipped)
print unzipped
# [(1, 2, 3), ('a', 'b', 'c')]
  • unzipped: tuple_1 = e1 de chaque tuple compressé. tuple_2 = e2 de chaquezipped

Notes de bas de page

  1. Un objet capable de renvoyer ses membres un par un (ex. List [1,2,3], string 'I like codin', tuple (1,2,3), dictionary {'a': 1, 'b' : 2})
  2. {clé1: valeur1, clé2: valeur2 ...}
  3. «Déballage» (*)

* Code:

# foo - function, returns sum of two arguments
def foo(x,y):
    return x + y
print foo(3,4)
# 7

numbers = [1,2]
print foo(numbers)
# TypeError: foo() takes exactly 2 arguments (1 given)

print foo(*numbers)
# 3

*a pris numbers(1 argument) et a «déballé» ses 2 éléments en 2 arguments


14

Fondamentalement, la fonction zip fonctionne sur les listes, les tuples et les dictionnaires en Python. Si vous utilisez IPython, tapez simplement zip? Et vérifiez en quoi consiste zip ().

Si vous n'utilisez pas IPython, installez-le simplement: "pip install ipython"

Pour les listes

a = ['a', 'b', 'c']
b = ['p', 'q', 'r']
zip(a, b)

La sortie est [('a', 'p'), ('b', 'q'), ('c', 'r')

Pour le dictionnaire:

c = {'gaurav':'waghs', 'nilesh':'kashid', 'ramesh':'sawant', 'anu':'raje'}
d = {'amit':'wagh', 'swapnil':'dalavi', 'anish':'mane', 'raghu':'rokda'}
zip(c, d)

La sortie est:

[('gaurav', 'amit'),
 ('nilesh', 'swapnil'),
 ('ramesh', 'anish'),
 ('anu', 'raghu')]

1
zip (c, d) joue zip (list (c), list (d))
Stephen Woodbridge

13

En Python 3 zip renvoie un itérateur à la place et doit être passé à une fonction de liste pour obtenir les tuples compressés:

x = [1, 2, 3]; y = ['a','b','c']
z = zip(x, y)
z = list(z)
print(z)
>>> [(1, 'a'), (2, 'b'), (3, 'c')]

Ensuite unzip, il suffit de conjuguer l'itérateur zippé:

x_back, y_back = zip(*z)
print(x_back); print(y_back)
>>> (1, 2, 3)
>>> ('a', 'b', 'c')

Si la forme originale de la liste est nécessaire au lieu des tuples:

x_back, y_back = zip(*z)
print(list(x_back)); print(list(y_back))
>>> [1,2,3]
>>> ['a','b','c']

1
La balise question indique Python 2.7; c'est pour Python 3. D'ailleurs, cette réponse le mentionne déjà.
0 0

8

Par souci d'exhaustivité.

Lorsque les longueurs des listes compressées ne sont pas égales. La longueur de la liste de résultats deviendra la plus courte sans qu'aucune erreur ne se soit produite

>>> a = [1]
>>> b = ["2", 3]
>>> zip(a,b)
[(1, '2')]

1

Je ne pense pas que ziprenvoie une liste. ziprenvoie un générateur. Vous devez faire list(zip(a, b))pour obtenir une liste de tuples.

x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
list(zipped)

1
La balise question indique Python 2.7; c'est pour Python 3. D'ailleurs, cette réponse le mentionne déjà.
0 0

1

Cela vaut la peine d'ajouter ici car c'est une question très bien classée sur zip. zipest génial, Python idiomatique - mais il ne s'adapte pas très bien du tout aux grandes listes.

Au lieu de:

books = ['AAAAAAA', 'BAAAAAAA', ... , 'ZZZZZZZ']
words = [345, 567, ... , 672]

for book, word in zip(books, words):
   print('{}: {}'.format(book, word))

Utilisez izip. Pour le traitement moderne, il le stocke dans la mémoire cache L1 et est beaucoup plus performant pour les listes plus grandes. Utilisez-le aussi simplement que d'ajouter un i:

for book, word in izip(books, words):
   print('{}: {}'.format(book, word))
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.