Поштові списки в 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, що не те, що я очікував. Я очікував три. Я думаю, я роблю щось принципово неправильне.


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

Звичайно, це не спрацює, якщо списки були порожніми для початку.


1
len (результат [0]) не буде працювати. Об'єкт 'zip' не піддається підписці
GilbertS

2
@GilbertS в Python 2 zipповернув список. У Python 3 це ітератор
Tomerikoo

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...

і "перетягує" їх у один список, записи якого є трьома корчами (ai, bi, ci). Уявіть, як намалювати блискавку по горизонталі зліва направо.



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

Я очікую, що ви намагаєтесь це створити кортеж, де кожен елемент є списком.


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 tuple = (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',)]

Zip в дії!

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], рядок 'Мені подобається кодін', кортеж (1,2,3), словник {'a': 1, 'b' : 2})
  2. {key1: value1, key2: value2 ...}
  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 арг) і "розпакував" свої 2 елементи на 2 аргументи


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

1
zip (c, d) виконує zip (list (c), list (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']

1
Тег питання констатує Python 2.7; це для Python 3. Крім того, ця відповідь вже згадує про це.
0 0

8

Заради повноти.

Коли довжина списків довжини не дорівнює. Тривалість списку результатів стане найкоротшою, без будь-яких помилок

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

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))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.