Python Iterate Over Multiple Lists at Once
Iterating over lists is a fundamental concept in programming and if we are being honest, a very easy thing to grasp the concept of. However there are times where you are presented with 2 or more lists that relate to each other that you need to iterate over in unison to extract values from. Because this is such a common thing Python's standard library has a way of doing this in a clean way, in this post I will demonstrate a few ways this task can be done and my recommendation on implementing them.
Commonly Seen Not Recommended
People that come from other languages will often use enumerate
to get an index while looping over one list, and extracting the value of the other 2 lists with that index, and then further process the data. That solution will look somewhat like the code block below.
first_names = ['Tony', 'Amy', 'Bob']
last_names = ['Robbins', 'Smith', 'Barker']
job_titles = ['Speaker', 'Author', 'Host']
for index, first_name in enumerate(first_names):
last_name = last_names[index]
job_title = job_titles[index]
print(f'{first_name} {last_name} is a talented {job_title}')
Which will give the following output
$ python myscript.py
Tony Robbins is a talented Speaker
Amy Smith is a talented Author
Bob Barker is a talented Host
$
And it works as expected, however if any of those lists do not have the same number of elements it will throw an index error and unless caught your program will fail. You can see this by deleting any one of the elements from a single list and re run the script.
Iterating Over All Lists at Once
The secret to this is using the built in function zip
which is in Python's standard library. Below I have modified the example above to use zip, and not only are we using less code but it is more clear what the for loop is doing by just reading the for declaration.
first_names = ['Tony', 'Amy', 'Bob']
last_names = ['Robbins', 'Smith', 'Barker']
job_titles = ['Speaker', 'Author', 'Host']
for first_name, last_name, job_title in zip(first_names, last_names, job_titles):
print(f'{first_name} {last_name} is a talented {job_title}')
And we get the same output
$ python myscript.py
Tony Robbins is a talented Speaker
Amy Smith is a talented Author
Bob Barker is a talented Host
$
And now where it is really beneficial is if we have lists that are not the same size, we do not hit an exception that we have to catch. Below is the output if I remove the 'Host'
element from the job_titles
list.
$ python myscript.py
Tony Robbins is a talented Speaker
Amy Smith is a talented Author
$
We don't get an exception, it just stops looping when one list runs out of elements.
Don't Break Out of Loop When List Runs Out
Lets say you need to continue looping over elements until you reach the end of the longest list. You can do this with itertools.zip_longest
. Below I have a snippet of code that uses that instead of zip
.
from itertools import zip_longest
first_names = ['Tony', 'Amy', 'Bob']
last_names = ['Robbins', 'Smith', 'Barker']
job_titles = ['Speaker', 'Author']
for first_name, last_name, job_title in zip_longest(first_names, last_names, job_titles):
print(f'{first_name} {last_name} is a talented {job_title}')
- Notice I import zip_longest from itertools on the first line
- Notice how the job_titles list has 2 elements and the other lists have 3.
As you can see the code is very similar to using zip other than importing and calling zip_longest
versus just using zip, but lets take a look at the output if we run this code.
$ python myscript.py
Tony Robbins is a talented Speaker
Amy Smith is a talented Author
Bob Barker is a talented None
$
As you can see zip_longest will return None
for any list that has run out of elements.
Considerations
Not sure if you noticed but it is worth pointing out that it is implied that all of the lists you are iterating over are related in the fact that each sequential element of each list has some sort of relationship to the elements in the other lists at that same index. Meaning that the data in each of your list's can't be in a random order.
And thats it between zip
and itertools.zip_longest
you should be able to iterate over multiple lists at once in most circumstances while avoiding using indices. If you have questions please leave a comment so I can clear up any confusion.