Перейти к содержимому

Zip python что это

  • автор:

Введение

В Python есть несколько встроенных функций, которые делают код очень элегантным. Одна из них — функция zip . Но начинающим не всегда бывает понятно, как её использовать, и порой это приводит к ошибкам.

Например, возьмём матрицу 2*3, представленную вложенным списком:

matrix = [[1, 2, 3], [1, 2, 3]]

И попробуем ответить на распространённый на собеседованиях по Python вопрос:

Junior developer в ответ напишет несколько циклов for , в то время как senior ограничится всего одной строчкой кода:

matrix_T = [list(i) for i in zip(*matrix)]

Если это однострочное решение пока что непонятно, не стоит переживать: дальше в статье мы подробно рассмотрим принцип действия мощной функции zip на девяти уровнях использования с полезными советами и хитрыми приёмами.

Если же такое решение вам знакомо, продолжайте читать статью и вы узнаете о ещё более крутых трюках и хитростях функции zip . ��

Уровень 0: как функция zip используется обычно

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

Вот пример её применения для объединения двух списков:

id = [1, 2, 3, 4]
leaders = ['Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou']
record = zip(id, leaders)

print(record)
#

print(list(record))
# [(1, 'Elon Mask'), (2, 'Tim Cook'), (3, 'Bill Gates'), (4, 'Yang Zhou')]

Здесь функция zip возвращает итератор кортежей, где i-й кортеж содержит i-й элемент из каждого списка.

Принцип работы напоминает обычную застёжку-молнию.

Уровень 1: Zip работает с любым количеством итерируемых объектов

На самом деле функция zip в Python намного мощнее застёжки-молнии. Она имеет дело не с двумя, а с любым количеством итерируемых объектов одновременно.

Вот мы передаём в функцию zip один список:

id = [1, 2, 3, 4]
record = zip(id)
print(list(record))
# [(1,), (2,), (3,), (4,)]

А как насчёт трёх списков?

id = [1, 2, 3, 4]
leaders = ['Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou']
sex = ['male', 'male', 'male', 'male']
record = zip(id, leaders, sex)

print(list(record))
# [(1, 'Elon Mask', 'male'), (2, 'Tim Cook', 'male'), (3, 'Bill Gates', 'male'), (4, 'Yang Zhou', 'male')]

То есть неважно, сколько итерируемых объектов передаётся в функцию zip : она в любом случае работает как надо.

Кстати, если аргумента нет, функция zip возвращает пустой итератор.

Уровень 2: работа с неравными по длине аргументами

В реальности данные не всегда чистые и полные: иногда приходится иметь дело с неравными по длине итерируемыми объектами. По умолчанию результат функции zip берётся по длине самого короткого итерируемого объекта.

id = [1, 2]
leaders = ['Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou']
record = zip(id, leaders)

print(list(record))
# [(1, 'Elon Mask'), (2, 'Tim Cook')]

Так, в приведённом выше коде самый короткий список — это id . Поэтому record содержит только два кортежа, а два последних лидера в списке leaders были отброшены.

А что, если эти два последних лидера окажутся недовольны тем, как с ними поступили?

Python и здесь придёт на помощь. В модуле itertools есть функция zip_longest . Посмотрим, как с её помощью генерируется список record :

from itertools import zip_longest
id = [1, 2]
leaders = ['Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou']

long_record = zip_longest(id, leaders)
print(list(long_record))
# [(1, 'Elon Mask'), (2, 'Tim Cook'), (None, 'Bill Gates'), (None, 'Yang Zhou')]

long_record_2 = zip_longest(id, leaders, fillvalue='Top')
print(list(long_record_2))
# [(1, 'Elon Mask'), (2, 'Tim Cook'), ('Top', 'Bill Gates'), ('Top', 'Yang Zhou')]

Результат функции zip_longest основывается на самом длинном её аргументе. Дополнительный аргумент fillvalue , чьё значение по умолчанию равно None , помогает заполнить недостающие значения.

Уровень 3: операция распаковывания

Если в предыдущем примере получить сначала record , то как распаковать его на отдельные итерируемые объекты?

К сожалению, в Python нет функции распаковывания. Но если воспользоваться хитрыми приёмами звёздочек, распаковывание превращается в очень простую задачу.

record = [(1, 'Elon Mask'), (2, 'Tim Cook'), (3, 'Bill Gates'), (4, 'Yang Zhou')]
id, leaders = zip(*record)
print(id)
# (1, 2, 3, 4)
print(leaders)
# ('Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou')

С помощью звёздочки здесь выполнена операция распаковки: распакованы все четыре кортежа из списка record .

Если не прибегать к технике звёздочек, то же самое делается следующим методом:

record = [(1, 'Elon Mask'), (2, 'Tim Cook'), (3, 'Bill Gates'), (4, 'Yang Zhou')]

print(*record) # распаковываем список одной звёздочкой
# (1, 'Elon Mask') (2, 'Tim Cook') (3, 'Bill Gates') (4, 'Yang Zhou')

id, leaders = zip((1, 'Elon Mask'), (2, 'Tim Cook'), (3, 'Bill Gates'), (4, 'Yang Zhou'))
print(id)
# (1, 2, 3, 4)
print(leaders)
# ('Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou')

Уровень 4: Создание и обновление словарей

С помощью функции zip очень просто создавать или обновлять dict , задействуя отдельные списки. Есть два однострочных решения:

  • использование dict comprehension и zip ;
  • использование функции dict и zip .
id = [1, 2, 3, 4]
leaders = ['Elon Mask', 'Tim Cook', 'Bill Gates', 'Yang Zhou']

# создаём словарь, используя «dict comprehension»
leader_dict =
print(leader_dict)
#

# создаём словарь, используя функцию «dict»
leader_dict_2 = dict(zip(id, leaders))
print(leader_dict_2)
#

# обновляем
other_id = [5, 6]
other_leaders = ['Larry Page', 'Sergey Brin']
leader_dict.update(zip(other_id, other_leaders))
print(leader_dict)
#

В этом примере не используются циклы for . И насколько же элегантным он от этого становится, по-питоновски элегантным!

Уровень 5: функция zip вместо циклов for

Существует ещё один вариант применения, в котором функция zip заменяет цикл for , — это работа с последовательными элементами одной коллекции. Например, имеется список из целых чисел и надо вычислить разницу между соседними числами.

```numbers = [12, 3, 7, 15, 8]diff = [a-b for a, b in zip(numbers, numbers[1:])]result: [9, -4, -8, 7]

Уровень 6: сортировка списков

Кроме того, с помощью zip выполняется сортировка двух связанных друг с другом списков:

```
>>> list1 = [3,2,4,1, 1]
>>> list2 = [‘three’, ‘two’, ‘four’, ‘one’, ‘one2’]
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2
(‘one’, ‘one2’, ‘two’, ‘three’, ‘four’)
```

Уровень 7: применение функции zip в циклах for

Типичный сценарий — когда имеешь дело с несколькими итерируемыми объектами одновременно. Функция zip показывает себя во всей красе, если задействовать её вместе с циклами for .

Продемонстрируем это на следующем примере:

products = ["cherry", "strawberry", "banana"]
price = [2.5, 3, 5]
cost = [1, 1.5, 2]
for prod, p, c in zip(products, price, cost):
print(f'The profit of a box of is £!')
# Прибыль от одного ящика вишни составляет 1,5 фунта!
# Прибыль от одного ящика клубники составляет 1,5 фунта!
# Прибыль от одного ящика бананов составляет 3 фунта!

Есть ли более элегантная реализация этого примера?

Уровень 8: транспонирование матрицы

Наконец, мы возвращаемся к распространённому на собеседованиях по Python вопросу:

Теперь, когда мы уже имеем представление о функции zip , распаковывании с помощью звёздочки и list comprehensions , однострочное решение будет более чем очевидным:

matrix = [[1, 2, 3], [1, 2, 3]]
matrix_T = [list(i) for i in zip(*matrix)]
print(matrix_T)
# [[1, 1], [2, 2], [3, 3]]

Заключение

Функция zip в Python очень полезная и мощная. Правильное её использование помогает писать меньше кода, выполняя при этом больше операций. «Делай больше, используя меньше» — такова философия Python.

№38 Функция zip() / для начинающих

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

В Python есть несколько встроенных функций, которые позволяют перебирать данные. Одна из них — zip. Функция zip() в Python создает итератор, который объединяет элементы из нескольких источников данных.

У функции zip() множество сценариев применения. Например, она пригодится, если нужно создать набор словарей из двух массивов, каждый из которых содержит имя и номер сотрудника.

В этом материале разберемся с основами этой функции, познакомимся с отличиями в Python 2 и Python 3, а также узнаем, в каких ситуациях zip() может быть полезна.

Обновление итератора Python

В Python итерация — это процесс прохождения программы по списку. Например, если есть цикл for, который выводит название каждой сферы, которой занимается компания, можно сказать, что программа выполняет итерацию (перебирает) списка названий.

Итерируемый объект же — это объект, который может возвращать отдельные элементы. Таким образом массивы — это итерируемые объекты, потому что можно вывести каждый отдельный элемент с помощью цикла for. Основы итерации в Python вспомнили — теперь можно переходить и к функции zip() .

Пример работы функция zip() в Python

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

Предположим, что есть список имен и номером сотрудников, и их нужно объединить в массив кортежей. Для этого можно использовать функцию zip() . Вот пример программы, которая делает именно это:

 
employee_numbers = [2, 9, 18, 28]
employee_names = ["Дима", "Марина", "Андрей", "Никита"]

zipped_values = zip(employee_names, employee_numbers)
zipped_list = list(zipped_values)

print(zipped_list)

Функция zip возвращает следующее:

[('Дима', 2), ('Марина', 9), ('Андрей', 18), ('Никита', 28)]

Эта программа создала массив из кортежей, каждый из которых содержит имя и номер сотрудника. Здесь много составляющих, поэтому разберем по порядку. На первых двух строках объявляются переменные, которые хранят номера и имена сотрудников. На следующей — функция zip() объединяет два списка вместе, создавая новый массив кортежей.

На следующей строке zip-элемент конвертируется в список так, чтобы его можно было выводить и использовать как список. И на финальной строке он уже и выводится.

Можно убедиться в том, что zipped_values — это элемент zip() , воспользовавшись следующим кодом:

Работа с функцией zip в Python

Часто при работе с данными на Python возникает ситуация, когда необходимо преобразовать список кортежей в два отдельных списка, где первый список содержит первые элементы всех кортежей, а второй — вторые элементы.

Приведем пример. Допустим, есть список кортежей, каждый из которых содержит букву и соответствующее ей число:

data = [('a', 1), ('b', 2), ('c', 3), ('d', 4)]

Нужно преобразовать этот список в следующий формат:

result = (['a', 'b', 'c', 'd'], [1, 2, 3, 4])

В Python есть встроенная функция zip(), которая позволяет решить эту задачу.

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

x = [1, 2, 3] y = [4, 5, 6] zipped = zip(x, y) print(list(zipped)) # Выведет: [(1, 4), (2, 5), (3, 6)]

Также функция zip() может быть использована для «расстегивания» списка кортежей обратно в отдельные списки. Для этого используется оператор «*». Он позволяет преобразовать список в набор аргументов для функции.

zipped = [(1, 4), (2, 5), (3, 6)] x, y = zip(*zipped) print(list(x)) # Выведет: [1, 2, 3] print(list(y)) # Выведет: [4, 5, 6]

Таким образом, для преобразования списка кортежей в два списка можно использовать следующий код:

data = [('a', 1), ('b', 2), ('c', 3), ('d', 4)] x, y = zip(*data) result = (list(x), list(y)) print(result) # Выведет: (['a', 'b', 'c', 'd'], [1, 2, 3, 4])

В этом коде функция zip() с оператором «*» преобразует список кортежей в два отдельных кортежа. Затем каждый из этих кортежей преобразуется в список с помощью функции list().

Функция zip

В Pyhon функция zip позволяет пройтись одновременно по нескольким итерируемым объектам (спискам и др.):

>>> a = [10, 20, 30, 40] >>> b = ['a', 'b', 'c', 'd', 'e'] >>> for i, j in zip(a, b): . print(i, j) . 10 a 20 b 30 c 40 d

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

>>> for i in zip(a, b): . print(i, type(i)) . (10, 'a') (20, 'b') (30, 'c') (40, 'd')

В списке b на один элемент больше. Функция zip() возвращает итератор, который останавливается, когда исчерпывается самая короткая последовательность. Если требуется учесть все значения из самой длинной, то следует использовать функцию zip_longest() из модуля itertools :

>>> a = [10, 20, 30, 40] >>> b = ['a', 'b', 'c', 'd', 'e'] >>> c = [1.1, 1.2] >>> for i in itertools.zip_longest(a,b,c): . print(i) . (10, 'a', 1.1) (20, 'b', 1.2) (30, 'c', None) (40, 'd', None) (None, 'e', None)

Как мы видим, если элемента не хватает, то по-умолчанию подставляется объект None . Можно указать свой вариант заполнения:

>>> for i in itertools.zip_longest(a,b,c, fillvalue=0): . print(i) . (10, 'a', 1.1) (20, 'b', 1.2) (30, 'c', 0) (40, 'd', 0) (0, 'e', 0)

Если требуется получить не итератор, возвращаемый zip() , а список из элементов, то к объекту zip применима функция list() , которая преобразует итератор в список:

>>> a = [10, 20, 30, 40] >>> c = [1.1, 1.2, 1.3, 1.4] >>> ac = zip(a, c) >>> type(ac) >>> ac = list(ac) >>> type(ac) >>> ac [(10, 1.1), (20, 1.2), (30, 1.3), (40, 1.4)]

При написании программ на Python функцию zip нередко применяют для выполнения совместных или одновременных действий над элементами разных списков.

>>> values = [1.34, 3.25, 2.99] >>> coefficient = [3, 2, 2] >>> for i, j in zip(values, coefficient): . print(i*j) . 4.0200000000000005 6.5 5.98 >>> a = [] >>> b = [] >>> for i, j in zip(range(10,20), range(1,10)): . a.append(i) . b.append(j) . >>> a [10, 11, 12, 13, 14, 15, 16, 17, 18] >>> b [1, 2, 3, 4, 5, 6, 7, 8, 9]

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *