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() 函數將填充缺失的元素。

使用標準庫itertools模塊中的zip_longest(),可以在每個列表的元素個數不同時,用任意值填充缺失的元素。

默認情況下,它填充為 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'>

如果要將多個可迭代對象的元素列表作為元組獲取,請使用 list() 製作列表。

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