Встроенная функция zip() в Python позволяет объединить элементы из нескольких коллекций (таких как списки, словари, кортежи или строки) в один набор кортежей. Объединяемые коллекции передаются в качестве параметра через запятую:
zip(*iterables)
В качестве результата функция возвращает итератор на набор кортежей, где каждый кортеж содержит элементы из соответствующей позиции коллекций-параметров. Например, 1-й кортеж содержит 1-е элементы из каждой коллекции, 2-й кортеж содержит 2-е элементы из каждой коллекции и так далее. Причем итератор останавливается, когда завершается самая короткая коллекция-параметр. То есть по сути на выходе мы получим набор, где количество кортежей равно количеству элементов в наименьшей объединяемой коллекции.
Простой, но показательный пример:
names = ["Tom", "Bob", "Sam"]
ages = [41, 46, 35]
for user in zip(names, ages):
print(user)
# Консольный вывод
# ("Tom", 41)
# ("Bob", 46)
# ("Sam", 35)
В данном случае в функцию zip() передаются две коллекции-списка, каждый из которых содержит по 3 элемента. Функция zip() объединяет элементы из соответствующих позиций каждого списка в отдельный кортеж. В итоге мы получим три кортежа по два элемента (так как у нас 2 списка по элемента). В примере выше с помощью цикла перебираем результат функции и помещаем каждый его элемент - кортеж в переменную user.
Естественно мы можем сразу разложить полученный кортеж на отдельные переменные:
names = ["Tom", "Bob", "Sam"]
ages = [41, 46, 35]
for name, age in zip(names, ages):
print(f"Name: {name} Age: {age}")
# Консольный вывод
# Name: Tom Age: 41
# Name: Bob Age: 46
# Name: Sam Age: 35
Также мы могли бы получить результат функции в отдельную переменную и затем ее перебрать:
names = ["Tom", "Bob", "Sam"]
ages = [41, 46, 35]
users = zip(names, ages)
print(users) # <zip object at 0x7c2307627c40>
for user in users:
print(user)
Обратите внимание, что результат функции - именно итератор (zip-объект), а не список кортежей или кортеж кортежей...
При вызове без аргументов функция zip() возвращает пустой итератор:
for tup in zip():
print(tup) # ничего не выведет
С одним аргументом итерируемого объекта он возвращает итератор 1-кортежей.
# передаем список с одинм элементом
for tup in zip([5]):
print(tup) # (5,)
# передаем кортеж с одним элементом
for tup in zip((6,)):
print(tup) # (6,)
# передаем словарь с одним элементом
for tup in zip({1: "Tom"}):
print(tup) # (1,)
Размер возвращаемых кортежей соответствует количеству переданных в функцию коллекций. Например, если в функцию передается одна коллекция, например, список, то для каждого элемента создается свой одноэлементный кортеж:
# передаем список с одинм элементом
for tup in zip([5, 6, 7]):
print(tup)
# Консольный вывод
# (5,)
# (6,)
# (7,)
Если списки имеют разную длину, zip() останавливается на самом коротком из них:
list1 = [1, 2, 3]
list2 = ["a", "b"]
for tup in (zip(list1, list2)):
print(tup)
# Консольный вывод
# (1, "a")
# (2, "b")
Рассмотрим распространенные задачи, которые мы можем решить с помощью функции zip().
Наиболее распростраенным вариантом использования функции zip() является объединение списков. Например, в первом примере выше объединялись два списка - имена пользователей и возрасты пользователей в ряд кортежей, каждый из которых представляет отдельного пользователя. Мы можем пойти дальше и получить единый список из кортежей:
names = ["Tom", "Bob", "Sam"]
ages = [41, 46, 35]
users = list(zip(names, ages))
print(users) # [("Tom", 41), ("Bob", 46), ("Sam", 35)]
for user in users:
print(user)
# Консольный вывод
# ("Tom", 41)
# ("Bob", 46)
# ("Sam", 35)
Подобным образом можно объединять и большее количество списков:
names = ["Tom", "Bob", "Sam"]
ages = [41, 46, 35]
companies = ["Sber", "VK", "Yandex"]
users = list(zip(names, ages, companies))
print(users) # [("Tom", 41, "Sber"), ("Bob", 46, "VK"), ("Sam", 35, "Yandex")]
for user in users:
print(user)
# Консольный вывод
# ("Tom", 41, "Sber")
# ("Bob", 46, "VK")
# ("Sam", 35, "Yandex")
Если у нас есть список кортежей, мы можем разложить его на отдельные кортежи:
users = [("Tom", 41), ("Bob", 46), ("Sam", 35)]
names, ages = zip(*users)
print(names) # ("Tom", "Bob", "Sam")
print(ages) # (41, 46, 35)
Можно использовать функцию, если нам надо пройтись одновременно по нескольким спискам:
names = ["Tom", "Bob", "Sam"]
ages = [41, 46, 35]
for name, age in zip(names, ages):
print(f"Name: {name} Age: {age}")
# Консольный вывод
# Name: Tom Age: 41
# Name: Bob Age: 46
# Name: Sam Age: 35
Можно сопоставлять элементы в различных списках/кортежах и получить словарь, где ключи - элементы одного списка, а значения - элементы второго списка:
keys = ["name", "age", "city"]
values = ["Tom", 41, "Volgograd"]
user = dict(zip(keys, values))
print(user) # {"name": "Tom", "age": 41, "city": "Volgograd"}
Объединение диапазонов или последовательностей:
numbers = range(1, 4) letters = ["a", "b", "c"] result = list(zip(numbers, letters)) print(result) # [(1, "a"), (2, "b"), (3, "c")]
Функцию zip() удобно использовать при сравнении элементов двух списков:
list1 = [1, 2, 3] list2 = [1, 4, 3] comparison = [a == b for a, b in zip(list1, list2)] print(comparison) # [True, False, True]