Python, Using the zip() function: Getting the elements of multiple lists at once

Money and Business

Python's built-in function zip() combines the elements of multiple iterable objects (lists, tuples, etc.) and is used to retrieve the elements of multiple lists in a for loop.

This section describes the following usage of the zip() function.

  • Get the elements of multiple lists in a for loop.
  • Dealing with different number of elements
    • zip():The function will ignore the elements that are too much.
    • itertools.zip_longest():This function will fill in the missing elements.
  • Get a list of tuples of elements of multiple iterables.

Get the elements of multiple lists in a for loop.

If you want to retrieve and use the elements of multiple iterable objects (lists, tuples, etc.) at the same time in a for loop, specify them as arguments to the zip() function.

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

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

Not just two, but three or more as well.

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

Dealing with different number of elements

The zip() function ignores a large number of elements.

In the zip() function, if the number of elements in each list is different, up to the lesser (shorter) number of elements will be returned, and the greater number will be ignored.

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

The itertools.zip_longest() function will fill in the missing elements.

Using zip_longest() in the standard library itertools module, it is possible to fill in the missing elements with arbitrary values when the number of elements in each list is different.

By default, it is filled with 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

If the fillvalue argument is specified, it will be filled with that value.

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

Even if there are multiple lists with missing elements, the value to be filled is uniform. It is not possible to specify different values.

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

It is possible to specify a different value by using zip_longest() inside zip_longest(), but it is not practical because you need to know in advance which elements of the list are missing.

If you want to fill multiple lists with an unknown number of elements, each with a different value, the following procedure can be considered.

  1. Define values to fill for all lists.
  2. Get the maximum number of elements
  3. Fill all lists to the maximum number of elements
  4. Using the zip() function
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

In the process of filling up to the largest number of elements, we do the following.

  • Initializing a list with an arbitrary value and number of elements
  • + operator to join lists together

If we turn this into a function, it looks like this. The original list and the values that fill the list are specified as iterables (list or tuple) arguments, respectively.

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

It uses list comprehension notation and list expansion by *.

Get a list of tuples of elements of multiple iterables.

The zip() function returns an iterator (zip object) that is a tuple of elements of multiple iterable objects.
It can also be used outside the for loop, and the target is not limited to lists.

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

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

If you want to get a list of the elements of multiple iterable objects as a tuple, use list() to make a 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'>