Image of Python Zip Two Lists

ADVERTISEMENT

Table of Contents

Introduction

Python has a vast array of built-in functions that help us quickly implement an algorithm, that would otherwise take much more time to create ourselves. The accessibility of these builtins is part of what makes Python such a powerful programming language. One of these useful functions is the zip() function.

In this article, we will explore how we can zip two lists with Python's zip() function. We will also look at other concepts such as lists, tuples, and a lesser known use of the * symbol, which will allow us to utilize the zip() function to its fullest.

Brief overview of lists and tuples

A list is a data structure in Python. Generally, in programming, it's known as an array. Lists contain a set of ordered elements. We can access individual elements from a list by indexing. For example:

>>> list_x = [1, 2, 'a', 'b']
>>> list_x[0]
1
>>> list_x[2]
'a'
>>> list_x[1]
2

Here, we define list_x containing integers and strings. Then we use the syntax shown in the example to get an object from the list. List indexes start with 0 for the first item in the list. We can even store lists inside lists:

>>> list_y = [[1, 2], ['a', 'b']]
>>> list_y[0]
[1, 2]

Tuples are another data type in Python which are very similar to lists. The difference is that tuples are not mutable, unlike lists. This means we can't change the contents in the tuples once defined. For example:

>>> tuple_x = (1, 2, 3)
>>> tuple_x[0]
1
>>> tuple_x[0] = 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> 
>>> list_x = [1, 2, 'a', 'b']
>>> 
>>> list_x[0] = 100
>>> print(list_x)
[100, 2, 'a', 'b']

In this example, we see that tuples use parentheses instead of brackets. We can get items from a tuple just like we do with lists. However, if we try to change items in the tuple we get an error. A list on the other hand allows us to change its items.

Alternative use of the * symbol in Python

If you have worked with Python, you surely have used the asterisk symbol * for multiplication. However, you may have also seen the * symbol used in front of variables. But what does it actually do?

The * operator can be used in front of a variable in a function definition or a function call. It takes arguments from the variable (which should store an iterable) and unpacks them as arguments for the function. For example:

>>> def func(x, y):
...     return x, y
... 
>>> list_x = [1, 2]
>>> 
>>> print(func(*list_x))
(1, 2)

Here, we have a function that takes 2 arguments and returns those arguments as a tuple. With the use of the * operator, we can store the 2 arguments in a list and then unpack those arguments directly in the function call. Using it in a function definition stores all the arguments in the tuple which is assigned to the variable.

>>> def func1(*args):
...     print(args)
... 
>>> func1(1, 2, 3, 4)
(1, 2, 3, 4)

This operator is often used with the zip() function in Python.

How can we zip two lists in Python?

The zip() built-in function in Python is used to join together tuples or lists. The way the function joins them can be best understood with an example:

>>> zipped_list = zip([1, 2, 3], [3, 4, 5])
>>> print(zipped_list)
<zip object at 0x7fd928b1f540>
>>> list(zipped_list)
[(1, 3), (2, 4), (3, 5)]
>>> 

The example above shows us how two lists can be joined based on their corresponding elements. All we have to do is use the two lists as arguments for the zip() function. In this example, we can see exactly what the zip function does. It takes each index from the lists supplied as arguments and puts them in one tuple. Meaning, all index 0 items go in the first tuple, all index 1 items go in the second tuple, and so on.

The output of the zip() function is an iterator, which means we have to apply the list() or tuple() functions to the output to access the final joined list. And since the output is an iterator we can use the next() function to get the zipped items one by one which has its own benefits.

Zipping lists of different lengths

Let's say we have to zip two different lists, but they have different lengths. How does the zip() function handle this situation?

If the lengths of the lists are different, the zip() function will only zip up until the point where it can find matching indexes. For example:

>>> list(zip([1, 2, 3, 4], [5, 6]))
[(1, 5), (2, 6)]

Here we can see that the zip() function stops joining indices after index 2 because the second list does not have an index 3.

Zipping more than two lists

We can actually zip together more than one list. For example:

>>> list(zip([1, 2, 3], [4, 5, 6], [7, 8, 9]))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

This example shows that we can zip more than two lists, by simply adding them to our zip() function. Furthermore, as we mentioned earlier this can also be done with the * operator:

>>> list_x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list(zip(*list_x))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> 
>>> list_x.append([10, 11, 12])
>>> list_x.append([13, 14, 15])
>>> list(zip(*list_x))
[(1, 4, 7, 10, 13), (2, 5, 8, 11, 14), (3, 6, 9, 12, 15)]
>>> 

Here, we see that we can use the * operator with the zip() function, to zip together the lists in list_x. Next, we see that after we add two more lists to list_x, we can still use the same line of code to zip together the lists. This is the advantage of the * operator. We can zip together multiple lists without knowing how many lists we have in list_x.

Note that in the previous sections, we supplied list arguments in our examples, but we can do all the same operations with tuple arguments.

What is the inverse of the zip function?

The zip() function is used not only for zipping together multiple sequences, but also doing the inverse: unzipping them. We can do this using the * operator and the output of a zip() function with another zip() function as such:

>>> list_x = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> list(zip(*list_x))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> list(zip(*[(1, 4, 7), (2, 5, 8), (3, 6, 9)]))
[(1, 2, 3), (4, 5, 6), (7, 8, 9)]

Here, we see that using a zip on the output of the previous zip operation we can reverse the operation and get back our original list. The only difference is that the items inside the list are now tuples.

Summary

In this article, we first briefly went over what lists and tuples are in Python. Then we explored an alternative use of the * symbol. Using our knowledge of these concepts, we then looked at what the zip() function is in Python and saw various ways to use it. Finally, we looked at how we can reverse the whole zip operation.

Next Steps

If you're interested in learning more about the basics of Python, coding, and software development, check out our Coding Essentials Guidebook for Developers, where we cover the essential languages, concepts, and tools that you'll need to become a professional developer.

Thanks and happy coding! We hope you enjoyed this article. If you have any questions or comments, feel free to reach out to jacob@initialcommit.io.

Final Notes