# Understanding map, filter, and zip in Python

The purpose of this article is to understand how Python built-in functions map(), filter(), and zip() work to make you more efficient with processing data in Python!

I will go over how these functions work and provide use-cases with and without the functions to compare.

It is important to understand how these functions work, but there is a better way once you're finished reading this! Its called **Comprehensions** and I write about them in *Beginner Python Comprehensions*

## Map

Python's map() function is used to apply a function on all elements of a specified iterable and return a map object.

`map()`

will take 2 required positional arguments. 1.) A function to run against iterables. 2.) An iterable (ie. list).

```
map(func, [...])
```

The expected output of this would be a `map object`

with a memory position.

Lets take an example that applies the function `square()`

to a list of integers. The objective here is to get a list of squared numbers from our original `numbers`

list.

```
def square(number):
return number*number
```

```
numbers = [1,2,3,4,5]
```

### Without map()

```
def square(number):
return number*number
numbers = [1,2,3,4,5]
squared_numbers = []
for number in numbers:
squared = square(number)
squared_numbers.append(squared)
```

### With map()

```
def square(number):
return number*number
numbers = [1,2,3,4,5]
squared_numbers = map(square, numbers)
```

### What we observed:

- Using
`map()`

we don't need to create an empty list that we append to in a for loop. - We do not need to use
`square()`

with parenthesis as the function parameter, as`map()`

will call the function for us, we just pass the function object. -
`map()`

will run`square()`

for each item in`numbers`

.

## Filter

Python's filter() function checks a condition of each element in an iterable and returns a filtered data structure only containing elements who match the given conditions.

`filter()`

will take 2 required positional arguments. 1.) A function to run against iterables. 2.) An iterable (ie. list).

```
filter(func, [...])
```

The function passed to `filter()`

must return a boolean (`True`

or `False`

)

The expected output of this would be a `filter object`

with a memory position.

Lets take an example that applies the function `even()`

to a list of integers. The objective here is to get a list that only contains even numbers.

```
def even(number):
if (number % 2) == 0:
return True
return False
```

```
numbers = [1,2,3,4,5]
```

### Without filter()

```
def even(number):
if (number % 2) == 0:
return True
return False
numbers = [1,2,3,4,5]
even_numbers = []
for number in numbers:
if even(number):
even_numbers.append(number)
```

### With filter()

```
def even(number):
if (number % 2) == 0:
return True
return False
numbers = [1,2,3,4,5]
even_numbers = filter(even, numbers)
```

### What we observed:

- Using
`filter()`

we don't need to create an empty list that we append to in a for loop. - We do not need to use
`even()`

with parenthesis as the function parameter, as`filter()`

will call the function for us, we just pass the function object. -
`filter()`

will run`even()`

for each item in`numbers`

and remove all elements that returned`False`

.

## Zip

Python's zip() function combines elements of 2 lists with matching indexes into an interable of tuples.

`zip()`

will take an undefined number of arguments where each argument is an iterable to zip.

```
zip([...], [...], [...], ...)
```

The expected output of this would be a `zip object`

containing tuples of the same-index element of each iterable with a memory position..

Let's take the above 2 examples combined to create a list of even numbers with their respective squared results.

```
def even(number):
if (number % 2) == 0:
return True
return False
def square(number):
return number*number
numbers = [1,2,3,4,5]
even_numbers = filter(even, numbers)
even_numbers_squared = map(square, even_numbers)
```

### Without zip()

```
...
even_numbers = [2,4]
even_numbers_squared = [4, 8]
combined = []
even_numbers_index = 0
for number in even_numbers:
squared = even_numbers_squared[even_numbers_index]
squared_tuple = (number, squared)
combined.append(squared_tuple)
```

### With zip()

```
...
even_numbers = [2,4]
even_numbers_squared = [4, 8]
zipped_result = zip(even_numbers, even_numbers_squared)
```

### What we observed:

- Using
`zip()`

we can combine values with matching indexes from multiple lists without creating a buffer list or iterating with a for loop.

## Conclusion

So hopefully with this you have a basic grasp on how these functions work, why they're useful, and how they can help you write more efficient and more readable Python code!

It is important to understand how these functions work, but there is a better way once you're finished reading this! Its called **Comprehensions** and I write about them in *Beginner Python Comprehensions*

## Top comments (11)

I almost never use

`map`

or`filter`

but it's good to know how they work. I use list comprehensions all the time though.A tip: you don't need to call

`list()`

on an iterable, unless you have a good reason to (like to print it as an example) you can just... iterate it :)This is a good intro on "functional Python": Functional Programming HOWTO

I predominantly use comprehensions as well, I actually completely forgot you could just iterate the objects so good call! I'm going to update this.

Hi. Sorry I am not very experienced but I spotted a couple of problems in your final bit about

`zip()`

.First off you try to iterate over

`even_numbers`

without calling`list()`

. I can see others have argued here that`list()`

is not necessary, and I am but a hobby programmer, so I know very little of the deeper layers of programming and maybe I am doing it wrong, but when I try to run the code snippets here, it only works if I call`list()`

on the`filter`

and`map`

returns. Otherwise I get errors in the`for`

loop (does not iterate in the loop without`list()`

on`filter`

, gives a`TypeError: 'map' object is not subscriptable`

.You set

`even_numbers_index = 0`

and then in the`for`

loop you set`squared = even_numbers_squared[even_numbers_index]`

but you never update`even_numbers_index`

so for each iteration in the loop you keep calling the same index number. When we extend the input list a bit to`numbers = [1,2,3,4,5,6,7,8]`

the result then becomes`[(2, 4), (4, 4), (6, 4), (8, 4)]`

giving an error in output compared to the intended.It works fine if we use

`zip()`

though and skip the for loop:`[(2, 4), (4, 16), (6, 36), (8, 64)]`

This is just in case others like me come by this otherwise great post to learn about

`map`

,`filter`

and`zip`

(and I really mean that. Short and well explained - thanks for that)Full code I was running:

Good catches! Sorry to be late to responding, but I'll make sure to edit these, thank you.

But remember, in Python comprehensions should be the first try for what could be done in map and filter.

Compressions can typically replace all 3 (map, filter, reduce) and can be used with zip.

The concepts here are still important to know. Libraries like pandas utilize the map syntax, or using a different language like JavaScript.

Absolutely, and thanks for commenting this, I hope everyone sees this as well!

I suppose you have to use the list() function on the result these three functions return because that's just an iterable instead of a list, right?

Correct. Map, filter, and zip objects are iterables, but we convert to a list for the sake of printing. :)

I am a little bit confused,

def square(number):

return number*number

even_numbers = [2,4]

correct me if I am wrong:

even_numbers_squared should be = [4, 16] instead of [4, 8]

Yupp you're correct! Just absent-mindedley added there instead apparently lol.