Listas postales en Python

151

Estoy tratando de aprender a "zip" listas. Para este fin, tengo un programa, donde en un punto particular, hago lo siguiente:

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

Esto me da tres listas, x1, x2, y x3, cada una de, por ejemplo, tamaño 20.

Ahora lo hago:

zipall = zip(x1, x2, x3)

Sin embargo, cuando lo hago:

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

Tengo 20, que no es lo que esperaba. Yo esperaba tres. Creo que estoy haciendo algo fundamentalmente incorrecto.

AJW
fuente
44
¿Qué es exactamente lo que esperas ziphacer? ¿Por qué deberías tener tres listas? ¿Cómo se verían?
Daniel Roseman
zip devuelve una lista de tuplas.
Demo

Respuestas:

225

Cuando zip()juntas tres listas que contienen 20 elementos cada una, el resultado tiene veinte elementos. Cada elemento es una tupla de tres.

Ver por ti mismo:

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 averiguar cuántos elementos contiene cada tupla, puede examinar la longitud del primer elemento:

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

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

Por supuesto, esto no funcionará si las listas estaban vacías para empezar.

NPE
fuente
1
len (resultado [0]) no funcionará. El objeto 'zip' no es subscriptable
GilbertS
2
@ GilbertS en Python 2 zipdevolvió una lista. En Python 3 es un iterador
Tomerikoo
63

zip toma un montón de listas de me gusta

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

y los "comprime" en una lista cuyas entradas son 3 tuplas (ai, bi, ci). Imagina dibujar una cremallera horizontalmente de izquierda a derecha.

Katriel
fuente
36

En Python 2.7 esto podría haber funcionado bien:

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

Pero en Python 3.4 debería ser (de lo contrario, el resultado será algo así <zip object at 0x00000256124E7DC8>):

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

zip crea una nueva lista, llena de tuplas que contienen elementos de los argumentos iterables:

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

Espero que intentes crear una tupla donde cada elemento sea una lista.

StoryTeller - Unslander Monica
fuente
14

Fuente: Mi publicación de blog (mejor formato)

Ejemplo

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

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

Entrada

Cero o más iterables [1] (ej. Lista, cadena, tupla, diccionario)

Salida (lista)

Primera tupla = (elemento_1 de números, elemento_1 de letras)

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

...

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

  1. Lista de n tuplas: n es la longitud del argumento más corto (entrada)
    • len (números) == 3 <len (letras) == 4 → corto = 3 → devuelve 3 tuplas
  2. Longitud de cada tupla = # de argumentos (la tupla toma un elemento de cada arg)
    • args = (números, letras); len (args) == 2 → tupla con 2 elementos
  3. ith tuple = (element_i arg1, element_i arg2 ..., element_i arg n)

Casos de borde

1) Cadena vacía: len (str) = 0 = sin tuplas

2) Cadena simple: len (str) == 2 tuplas con len (args) == 1 elemento (s)

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

¡Zip en acción!

1. Cree un diccionario [2] a partir de dos 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 es una solución elegante, clara y concisa

2. Imprimir columnas en una tabla

"*" [3] se llama "desempaque": 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 adicional: descomprimir

zip(*args) se llama "descomprimir" porque tiene el efecto 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 comprimida. tupla_2 = e2 de cadazipped

Notas al pie

  1. Un objeto capaz de devolver a sus miembros uno a la vez (ej. Lista [1,2,3], cadena 'Me gusta codin', tupla (1,2,3), diccionario {'a': 1, 'b' : 2})
  2. {clave1: valor1, clave2: valor2 ...}
  3. "Desembalaje" (*)

* 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

*tomó numbers(1 arg) y "desempaquetó" sus '2 elementos en 2 argumentos

JBallin
fuente
14

Básicamente, la función zip funciona en listas, tuplas y diccionarios en Python. Si está utilizando IPython, simplemente escriba zip? Y verifique de qué se trata zip ().

Si no está utilizando IPython, simplemente instálelo: "pip install ipython"

Para listas

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

La salida es [('a', 'p'), ('b', 'q'), ('c', 'r')

Para el diccionario:

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

El resultado es:

[('gaurav', 'amit'),
 ('nilesh', 'swapnil'),
 ('ramesh', 'anish'),
 ('anu', 'raghu')]
Wagh
fuente
1
zip (c, d) está realizando zip (lista (c), lista (d))
Stephen Woodbridge
13

En Python 3, en cambio, zip devuelve un iterador y debe pasarse a una función de lista para obtener las tuplas comprimidas:

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

Luego, para unzipellos, simplemente conjugan el iterador comprimido:

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

Si se necesita la forma original de la lista en lugar de las tuplas:

x_back, y_back = zip(*z)
print(list(x_back)); print(list(y_back))
>>> [1,2,3]
>>> ['a','b','c']
Shivid
fuente
1
La etiqueta de pregunta indica Python 2.7; esto es para Python 3. Además, esta respuesta ya menciona esto.
0 0
8

Por el bien de la integridad.

Cuando las longitudes de las listas comprimidas no son iguales. La longitud de la lista de resultados se convertirá en la más corta sin que se produzca ningún error.

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

No creo que zipdevuelva una lista. zipdevuelve un generador Tienes que hacer list(zip(a, b))para obtener una lista de tuplas.

x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
list(zipped)
Ankur Kothari
fuente
1
La etiqueta de pregunta indica Python 2.7; esto es para Python 3. Además, esta respuesta ya menciona esto.
0 0
1

Vale la pena agregar aquí, ya que es una pregunta de alta clasificación en zip. zipes genial, Python idiomático, pero no escala muy bien para listas grandes.

En vez de:

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

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

Uso izip. Para el procesamiento moderno, lo almacena en la memoria caché L1 y es mucho más eficaz para listas más grandes. Úselo tan simplemente como agregar un i:

for book, word in izip(books, words):
   print('{}: {}'.format(book, word))
Micheal J. Roberts
fuente