Python, Використання функції zip(): отримання елементів кількох списків одночасно

Бізнес

Вбудована функція Python zip() поєднує елементи кількох ітерованих об’єктів (списків, кортежів тощо) і використовується для отримання елементів кількох списків у циклі for.

У цьому розділі описано наступне використання функції zip().

  • Отримати елементи кількох списків у циклі for.
  • Робота з різною кількістю елементів
    • zip():Функція ігнорує елементи, яких надто багато.
    • itertools.zip_longest():Ця функція заповнить відсутні елементи.
  • Отримайте список кортежів елементів кількох ітераторів.

Отримати елементи кількох списків у циклі for.

Якщо ви хочете отримати й використовувати елементи кількох ітеративних об’єктів (списків, кортежів тощо) одночасно в циклі for, вкажіть їх як аргументи функції zip().

names = ['Alice', 'Bob', 'Charlie']
ages = [24, 50, 18]

for name, age in zip(names, ages):
    print(name, age)
# Alice 24
# Bob 50
# Charlie 18

Не тільки два, а три або більше.

points = [100, 85, 90]

for name, age, point in zip(names, ages, points):
    print(name, age, point)
# Alice 24 100
# Bob 50 85
# Charlie 18 90

Робота з різною кількістю елементів

Функція zip() ігнорує велику кількість елементів.

У функції zip() якщо кількість елементів у кожному списку різна, повертається до меншої (коротшої) кількості елементів, а більша кількість ігнорується.

names = ['Alice', 'Bob', 'Charlie', 'Dave']
ages = [24, 50, 18]

for name, age in zip(names, ages):
    print(name, age)
# Alice 24
# Bob 50
# Charlie 18

Функція itertools.zip_longest() заповнить відсутні елементи.

Використовуючи zip_longest() в модулі стандартної бібліотеки itertools, можна заповнити відсутні елементи довільними значеннями, якщо кількість елементів у кожному списку різна.

За замовчуванням він заповнений None.

from itertools import zip_longest

names = ['Alice', 'Bob', 'Charlie', 'Dave']
ages = [24, 50, 18]

for name, age in zip_longest(names, ages):
    print(name, age)
# Alice 24
# Bob 50
# Charlie 18
# Dave None

Якщо вказано аргумент fillvalue, він буде заповнений цим значенням.

for name, age in zip_longest(names, ages, fillvalue=20):
    print(name, age)
# Alice 24
# Bob 50
# Charlie 18
# Dave 20

Навіть якщо є кілька списків із відсутніми елементами, значення, яке потрібно заповнити, є однорідним. Неможливо вказати різні значення.

points = [100, 85]

for name, age, point in zip_longest(names, ages, points, fillvalue=20):
    print(name, age, point)
# Alice 24 100
# Bob 50 85
# Charlie 18 20
# Dave 20 20

Можна вказати інше значення, використовуючи zip_longest() всередині zip_longest(), але це непрактично, оскільки вам потрібно заздалегідь знати, які елементи списку відсутні.

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

  1. Визначте значення для заповнення для всіх списків.
  2. Отримайте максимальну кількість елементів
  3. Заповніть усі списки максимальною кількістю елементів
  4. Використання функції zip().
fill_name = 'XXX'
fill_age = 20
fill_point = 50

len_names = len(names)
len_ages = len(ages)
len_points = len(points)

max_len = max(len_names, len_ages, len_points)

names = names + [fill_name] * (max_len - len_names)
ages = ages + [fill_age] * (max_len - len_ages)
points = points + [fill_point] * (max_len - len_points)

print(names)
print(ages)
print(points)
# ['Alice', 'Bob', 'Charlie', 'Dave']
# [24, 50, 18, 20]
# [100, 85, 50, 50]

for name, age, point in zip(names, ages, points):
    print(name, age, point)
# Alice 24 100
# Bob 50 85
# Charlie 18 50
# Dave 20 50

У процесі заповнення до найбільшої кількості елементів робимо наступне.

  • Ініціалізація списку з довільним значенням і кількістю елементів
  • + оператор для об’єднання списків

Якщо ми перетворимо це на функцію, це виглядає так. Початковий список і значення, які заповнюють список, задаються як аргументи ітерації (список або кортеж) відповідно.

def my_zip_longest(iterables, fillvalues):
    max_len = max(len(i) for i in iterables)
    return zip(*[list(i) + [v] * (max_len - len(i)) for i, v in zip(iterables, fillvalues)])

for name, age, point in my_zip_longest((names, ages, points), ('XXX', 20, 50)):
    print(name, age, point)
# Alice 24 100
# Bob 50 85
# Charlie 18 50
# Dave 20 50

Він використовує нотацію розуміння списку та розширення списку за допомогою *.

Отримайте список кортежів елементів кількох ітераторів.

Функція zip() повертає ітератор (zip-об’єкт), який є набір елементів кількох ітерованих об’єктів.
Його також можна використовувати поза циклом for, і ціль не обмежується списками.

names = ['Alice', 'Bob', 'Charlie']
ages = (24, 50, 18)

z = zip(names, ages)
print(z)
print(type(z))
# <zip object at 0x10b57b888>
# <class 'zip'>

Якщо ви хочете отримати список елементів кількох ітерованих об’єктів у вигляді кортежу, скористайтеся списком (), щоб створити список.

l = list(zip(names, ages))
print(l)
print(type(l))
print(type(l[0]))
# [('Alice', 24), ('Bob', 50), ('Charlie', 18)]
# <class 'list'>
# <class 'tuple'>