Elenchi zip in Python


151

Sto cercando di imparare come "comprimere" gli elenchi. A tal fine, ho un programma, dove in un determinato punto, faccio quanto segue:

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

Questo mi dà tre liste, x1, x2, e x3, ognuno di, diciamo, 20 dimensioni.

Ora faccio:

zipall = zip(x1, x2, x3)

Tuttavia, quando lo faccio:

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

Ne ottengo 20, che non è quello che mi aspettavo. Me ne aspettavo tre. Penso di fare qualcosa di fondamentalmente sbagliato.


4
Che cosa esattamente ti aspetti zipdi fare? Perché dovresti avere tre elenchi: come sarebbero?
Daniel Roseman,

zip restituisce un elenco di tuple.
Demo

Risposte:


225

Quando si zip()riuniscono tre elenchi contenenti 20 elementi ciascuno, il risultato ha venti elementi. Ogni elemento è di tre tuple.

Vedi tu stesso:

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)]

Per scoprire quanti elementi contiene ciascuna tupla, puoi esaminare la lunghezza del primo elemento:

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

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

Naturalmente, questo non funzionerà se le liste erano vuote per cominciare.


1
len (risultato [0]) non funzionerà. L'oggetto 'zip' non è sottoscrivibile
GilbertS

2
@GilbertS in Python 2 ha ziprestituito un elenco. In Python 3 è un iteratore
Tomerikoo il

63

zip prende un sacco di elenchi di Mi piace

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

e li "zip" in un elenco le cui voci sono 3-tuple (ai, bi, ci). Immagina di disegnare una cerniera in orizzontale da sinistra a destra.



36

In Python 2.7 potrebbe aver funzionato bene:

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

Ma in Python 3.4 dovrebbe essere (altrimenti, il risultato sarà qualcosa di simile <zip object at 0x00000256124E7DC8>):

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

28

zip crea un nuovo elenco, pieno di tuple contenenti elementi dagli argomenti iterabili:

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

Mi aspetto che ciò che cerchi sia creare una tupla in cui ogni elemento sia un elenco.


14

Fonte: My Blog Post (formattazione migliore)

Esempio

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

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

Ingresso

Zero o più iterabili [1] (es. Elenco, stringa, tupla, dizionario)

Uscita (elenco)

1a tupla = (element_1 di numeri, element_1 di lettere)

2a tupla = (numeri e_2, lettere e_2)

...

n-esima tupla = (numeri e_n, lettere e_n)

  1. Elenco di n tuple: n è la lunghezza dell'argomento più breve (input)
    • len (numeri) == 3 <len (lettere) == 4 → breve = 3 → restituisce 3 tuple
  2. Lunghezza ogni tupla = # di args (la tupla prende un elemento da ogni arg)
    • args = (numeri, lettere); len (args) == 2 → tupla con 2 elementi
  3. ith tuple = (element_i arg1, element_i arg2…, element_i arg n)

Custodie per bordi

1) String vuota: len (str) = 0 = nessuna tupla

2) Single String: len (str) == 2 tuple con len (args) == 1 elemento (i)

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

Zip in Action!

1. Costruisci un dizionario [2] su due elenchi

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 è una soluzione elegante, chiara e concisa

2. Stampa le colonne in una tabella

"*" [3] è chiamato "decompressione": 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')

Credito extra: decompressione

zip(*args) si chiama "decompressione" perché ha l'effetto inverso di 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 di ogni tupla zippata. tuple_2 = e2 di ciascunozipped

Le note

  1. Un oggetto in grado di restituire i suoi membri uno alla volta (es. Elenco [1,2,3], stringa 'I like codin', tuple (1,2,3), dizionario {'a': 1, 'b' : 2})
  2. {chiave1: valore1, chiave2: valore2 ...}
  3. "Disimballaggio" (*)

* Codice:

# 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

*prese numbers(1 arg) e "scompattò" i suoi '2 elementi in 2 args


14

Fondamentalmente la funzione zip funziona su liste, tuple e dizionari in Python. Se stai usando IPython, basta digitare zip? E controlla di cosa tratta zip ().

Se non si utilizza IPython, è sufficiente installarlo: "pip install ipython"

Per gli elenchi

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

L'output è [('a', 'p'), ('b', 'q'), ('c', 'r')

Per dizionario:

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

L'output è:

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

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

13

In Python 3 zip restituisce invece un iteratore e deve essere passato a una funzione di elenco per ottenere le tuple compresse:

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

Quindi a unziploro indietro basta coniugare l'iteratore zippato:

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

Se è necessaria la forma originale dell'elenco anziché le tuple:

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

1
Il tag della domanda indica Python 2.7; questo è per Python 3. Inoltre, questa risposta lo menziona già.
0 0

8

Per completezza.

Quando le lunghezze degli elenchi zippati non sono uguali. La lunghezza dell'elenco dei risultati diventerà la più breve senza che si sia verificato alcun errore

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

1

Non credo ziprestituisca un elenco. ziprestituisce un generatore. Devi fare list(zip(a, b))per ottenere un elenco di tuple.

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

1
Il tag della domanda indica Python 2.7; questo è per Python 3. Inoltre, questa risposta lo menziona già.
0 0

1

Vale la pena aggiungere qui in quanto è una domanda così alta su zip. zipè fantastico, idiomatico Python - ma non si adatta molto bene per elenchi di grandi dimensioni.

Invece di:

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

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

Usa izip. Per l'elaborazione moderna, la memorizza nella memoria cache L1 ed è molto più performante per elenchi più grandi. Usalo semplicemente come aggiungere un i:

for book, word in izip(books, words):
   print('{}: {}'.format(book, word))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.