A blog about programming (usually scientific python), mathematics (usually game theory) and learning (usually student centred pedagogic approaches).

## Iterating over many lists at the same time in Python with `zip`

### 2018-11-23

When programming it is often necessary to iterate over two (or more) lists. This post will describe `zip`

: a fantastic tool for doing this in a clear and concise way.

As a running example, let us assume we would like to check if 3 numbers $a, b, c$ form a pythagorean triplet, in other words:

$$ a ^ 2 + b ^ 2 = c ^ 2 $$For the purpose of this example let us start by randomly creating 3 lists of numbers:

```
import random
random.seed(0)
upper_value = 50
number_of_values = 10 ** 5
list_of_a_values = [random.randint(1, upper_value + 1) for _ in range(number_of_values)]
list_of_b_values = [random.randint(1, upper_value + 1) for _ in range(number_of_values)]
list_of_c_values = [random.randint(1, upper_value + 1) for _ in range(number_of_values)]
```

Here are our first 5 values of $a$:

```
list_of_a_values[:5]
```

### A common approach¶

One commone approach would be to create a dummy variable that will keep track of a position that goes through all 3 lists:

```
pythagorian_triplets = []
for i in range(number_of_values):
if list_of_a_values[i] ** 2 + list_of_b_values[i] ** 2 == list_of_c_values[i] ** 2:
pythagorian_triplets.append(
(
list_of_a_values[i],
list_of_b_values[i],
list_of_c_values[i],
)
)
```

```
pythagorian_triplets
```

### Zipping our lists together¶

Another approach is to use python's `zip`

command, this will essentially "zip" the three lists together

```
pythagorian_triplets = []
for item in zip(list_of_a_values, list_of_b_values, list_of_c_values):
if item[0] ** 2 + item[1] ** 2 == item[2] ** 2:
pythagorian_triplets.append(item)
pythagorian_triplets
```

What `zip`

is doing here is taking a list of inputs, in this case `list_of_a_values, list_of_b_values, list_of_c_values`

(it can take any number of inputs) and returning a python object that can be iterated over. Each iteration takes an element from each of the inputs.

We can use python unpacking and list comprehensions to write this in a more compact way:

```
pythagorian_triplets = [(a, b, c) for a, b, c in zip(list_of_a_values, list_of_b_values, list_of_c_values)
if a ** 2 + b ** 2 == c ** 2]
pythagorian_triplets
```

### Unpacking and zipping¶

Using numpy we can in fact make this slightly more efficient as we can generate a large 3 by N array of random integers (note that numpy's random number generator does not follow the same seeded path as python's standard lib):

```
import numpy as np
```

```
np.random.seed(0)
random_integers = np.random.randint(1, upper_value, (3, number_of_values))
random_integers
```

We can now use python unpacking with the `*`

command to pass each row of our array directly to `zip`

without having to name them:

```
pythagorian_triplets = [(a, b, c) for a, b, c in zip(*random_integers)
if a ** 2 + b ** 2 == c ** 2]
pythagorian_triplets
```

`zip`

is one of those super handy python commands that once you've gotten the hang off you never want to be without, `enumerate`

is another such tool.