Zip-списки в Python

151

Я пытаюсь научиться "застегивать" списки. Для этого у меня есть программа, где в определенный момент я делаю следующее:

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

Это дает мне три списка, x1, x2, и x3, каждый, скажем, размер 20.

Теперь я делаю:

zipall = zip(x1, x2, x3)

Тем не менее, когда я делаю:

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

Я получаю 20, что не то, что я ожидал. Я ожидал три. Я думаю, что я делаю что-то в корне неправильно.

AJW
источник
4
Что именно вы ожидаете zipсделать? Почему у вас должно быть три списка - как они будут выглядеть?
Даниэль Розман
zip возвращает список кортежей.
Демо

Ответы:

225

Когда вы zip()объединяете три списка, содержащие по 20 элементов каждый, в результате получается двадцать элементов. Каждый элемент состоит из трех кортежей.

Посмотреть на себя:

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

Чтобы узнать, сколько элементов содержит каждый кортеж, вы можете проверить длину первого элемента:

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

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

Конечно, это не будет работать, если списки были пустыми для начала.

NPE
источник
1
len (результат [0]) не сработает. объект 'zip' не
подлежит
2
@GilbertS в Python 2 zipвернул список. В Python 3 это итератор
Томерику
63

zip занимает кучу списков лайков

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

и "упаковывает" их в один список, записи которого состоят из 3-х кортежей (ai, bi, ci). Представьте, что вы рисуете молнию горизонтально слева направо.

Katriel
источник
36

В Python 2.7 это могло бы работать нормально:

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

Но в Python 3.4 это должно быть (в противном случае результат будет примерно таким <zip object at 0x00000256124E7DC8>):

>>> a = b = c = range(20)
>>> list(zip(a, b, c))
Аджай
источник
28

zip создает новый список, заполненный кортежами, содержащими элементы из итерируемых аргументов:

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

Я ожидаю, что вы пытаетесь создать кортеж, в котором каждый элемент является списком.

Рассказчик - Unslander Monica
источник
14

Источник: мой блог (лучше форматирование)

пример

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

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

вход

Ноль или более итераций [1] (например, список, строка, кортеж, словарь)

Выход (список)

1-й кортеж = (элемент_1 из цифр, элемент_1 из букв)

2-й кортеж = (e_2 цифры, e_2 буквы)

...

n-й кортеж = (цифры e_n, буквы e_n)

  1. Список из n кортежей: n - длина самого короткого аргумента (входная)
    • len (цифры) == 3 <len (буквы) == 4 → короткий = 3 → вернуть 3 кортежа
  2. Длина каждого кортежа = количество аргументов (кортеж берет элемент из каждого аргумента)
    • args = (цифры, буквы); len (args) == 2 → кортеж с 2 элементами
  3. ith кортеж = (element_i arg1, element_i arg2…, element_i arg n)

Краевые Чехлы

1) Пустая строка: len (str) = 0 = нет кортежей

2) Одна строка: len (str) == 2 кортежа с len (args) == 1 элемент (ов)

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

Почтовый индекс в действии!

1. Создайте словарь [2] из двух списков

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 это элегантное, четкое и краткое решение

2. Печать столбцов в таблице

«*» [3] называется «распаковка»: 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')

Дополнительный кредит: распаковка

zip(*args) называется «расстегивание молнии», потому что он имеет обратный эффект 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 каждого сжатого кортежа. tuple_2 = e2 каждогоzipped

Сноски

  1. Объект, способный возвращать своих членов по одному (например, список [1,2,3], строка «I like codin», tuple (1,2,3), словарь {'a': 1, 'b') : 2})
  2. {ключ1: значение1, ключ2: значение2 ...}
  3. «Распаковка» (*)

* Код:

# 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

*взял numbers(1 arg) и «распаковал» его '2 элемента в 2 args

JBallin
источник
14

В основном функция zip работает со списками, кортежами и словарями в Python. Если вы используете IPython, тогда просто введите zip? И проверьте, что такое zip ().

Если вы не используете IPython, просто установите его: "pip install ipython"

Для списков

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

Выход [('a', 'p'), ('b', 'q'), ('c', 'r')

Для словаря:

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

Выход:

[('gaurav', 'amit'),
 ('nilesh', 'swapnil'),
 ('ramesh', 'anish'),
 ('anu', 'raghu')]
Wagh
источник
1
Почтовый индекс (c, d) выполняет почтовый индекс (список (c), список (d))
Стивен Вудбридж
13

В Python 3 zip вместо этого возвращается итератор, который необходимо передать в функцию списка, чтобы получить сжатые кортежи:

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

Тогда к unzipним обратно просто сопрягаем сжатый итератор:

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

Если вместо кортежей нужна оригинальная форма списка:

x_back, y_back = zip(*z)
print(list(x_back)); print(list(y_back))
>>> [1,2,3]
>>> ['a','b','c']
Shivid
источник
1
Тег вопроса указывает на Python 2.7; это для Python 3. Кроме того, этот ответ уже упоминает об этом.
0 0
8

Ради полноты.

Когда длины сжатых списков не равны. Длина списка результатов станет самой короткой без ошибок

>>> a = [1]
>>> b = ["2", 3]
>>> zip(a,b)
[(1, '2')]
transang
источник
1

Я не думаю, что zipвозвращает список. zipвозвращает генератор. Вы должны сделать, list(zip(a, b))чтобы получить список кортежей.

x = [1, 2, 3]
y = [4, 5, 6]
zipped = zip(x, y)
list(zipped)
Анкур Котари
источник
1
Тег вопроса указывает на Python 2.7; это для Python 3. Кроме того, этот ответ уже упоминает об этом.
0 0
1

Здесь стоит добавить, поскольку это очень важный вопрос о zip. zipотличный, идиоматичный Python - но он не очень хорошо масштабируется для больших списков.

Вместо того:

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

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

Использование izip. Для современной обработки он хранит ее в кэш-памяти L1 и гораздо эффективнее для больших списков. Используйте это так же просто, как добавление i:

for book, word in izip(books, words):
   print('{}: {}'.format(book, word))
Майкл Дж. Робертс
источник