Listas de zip em Python


151

Estou tentando aprender como "zipar" listas. Para esse fim, tenho um programa em que, em um determinado momento, faço o seguinte:

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

Isto dá-me três listas, x1, x2, e x3, cada um, digamos, tamanho 20.

Agora eu faço:

zipall = zip(x1, x2, x3)

No entanto, quando eu faço:

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

Eu recebo 20, o que não é o que eu esperava. Eu esperava três. Eu acho que estou fazendo algo fundamentalmente errado.


4
O que exatamente você espera zipfazer? Por que você deveria ter três listas - como elas seriam?
Daniel Roseman

zip retorna uma lista de tuplas.
Demo

Respostas:


225

Quando você zip()reúne três listas contendo 20 elementos cada, o resultado possui vinte elementos. Cada elemento é uma três-tupla.

Veja por si mesmo:

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

Para descobrir quantos elementos cada tupla contém, você pode examinar o comprimento do primeiro elemento:

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

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

Obviamente, isso não funcionará se as listas estiverem vazias para começar.


1
len (resultado [0]) não funcionará. Objeto 'zip' não é subscrito
GilbertS 23/02

2
@ GilbertS no Python 2 zipretornou uma lista. No Python 3 é um iterador
Tomerikoo 23/03

63

zip leva um monte de gostos de listas

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 os "fecha" em uma lista cujas entradas são de três tuplas (ai, bi, ci). Imagine desenhar um zíper horizontalmente da esquerda para a direita.



36

No Python 2.7, isso pode ter funcionado bem:

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

Mas no Python 3.4 deveria ser (caso contrário, o resultado será algo como <zip object at 0x00000256124E7DC8>):

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

28

zip cria uma nova lista, preenchida com tuplas contendo elementos dos argumentos iteráveis:

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

Espero que você tente criar uma tupla em que cada elemento seja uma lista.


14

Fonte: Minha postagem no blog (melhor formatação)

Exemplo

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

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

Entrada

Zero ou mais iteráveis ​​[1] (por exemplo, lista, string, tupla, dicionário)

Saída (lista)

1a tupla = (elemento_1 de números, elemento_1 de letras)

2a tupla = (e_2 números, e_2 letras)

...

n-ésima tupla = (números e_n, letras e_n)

  1. Lista de n tuplas: n é o comprimento do argumento mais curto (entrada)
    • len (números) == 3 <len (letras) == 4 → curto = 3 → retornar 3 tuplas
  2. Comprimento de cada tupla = # de args (tupla recebe um elemento de cada arg)
    • args = (números, letras); len (args) == 2 → tupla com 2 elementos
  3. itupla = (elemento_i arg1, elemento_i arg2…, elemento_i arg n)

Casos Edge

1) String vazia: len (str) = 0 = sem tuplas

2) String única: len (str) == 2 tuplas com len (args) == 1 elemento (s)

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

Zip em ação!

1. Crie um dicionário [2] de duas listas

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 é uma solução elegante, clara e concisa

2. Imprimir colunas em uma tabela

"*" [3] é chamado "desembalar": 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édito Extra: Descompactando

zip(*args) é chamado de "descompactar" porque tem o efeito inverso de 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 cada tupla compactada. tuple_2 = e2 de cadazipped

Notas de rodapé

  1. Um objeto capaz de retornar seus membros um de cada vez (ex. Lista [1,2,3], string 'eu gosto de codin', tupla (1,2,3), dicionário {'a': 1, 'b' : 2})
  2. {chave1: valor1, chave2: valor2 ...}
  3. "Desembalar" (*)

* Código:

# 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

*pegou numbers(1 arg) e descompactou seus '2 elementos em 2 args


14

Basicamente, a função zip funciona em listas, tuplas e dicionários em Python. Se você estiver usando IPython, basta digitar zip? E verifique o que é o zip ().

Se você não estiver usando o IPython, basta instalá-lo: "pip install ipython"

Para listas

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

A saída é [('a', 'p'), ('b', 'q'), ('c', 'r')

Para dicionário:

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

A saída é:

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

1
zip (c, d) está a efectuar fecho de correr (lista (C), lista (d))
Stephen Woodbridge

13

No Python 3, zip retorna um iterador e precisa ser passado para uma função de lista para obter as tuplas compactadas:

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

Então, para unzipeles de volta, basta conjugar o iterador compactado:

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

Se a forma original da lista for necessária em vez de tuplas:

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

1
A tag de pergunta indica o Python 2.7; isto é para Python 3. Além disso, esta resposta já menciona isso.
0 0

8

Pelo bem da integridade.

Quando o comprimento das listas compactadas não é igual. O comprimento da lista de resultados se tornará o menor, sem que ocorra qualquer erro

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

1

Eu não acho que zipretorna uma lista. zipretorna um gerador. Você precisa fazer list(zip(a, b))para obter uma lista de tuplas.

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

1
A tag de pergunta indica o Python 2.7; isto é para Python 3. Além disso, esta resposta já menciona isso.
0 0

1

Vale a pena adicionar aqui, pois é uma pergunta de alta classificação no zip. zipé ótimo, Python idiomático - mas não escala muito bem para grandes listas.

Ao invés de:

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

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

Use izip. Para o processamento moderno, ele o armazena na memória L1 Cache e tem muito mais desempenho em listas maiores. Use-o simplesmente como adicionar um i:

for book, word in izip(books, words):
   print('{}: {}'.format(book, word))
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.