This article is going to try to shed some light on how to convert map, reduce and filter (often used with lambda expressions) in python into a syntax conforming to “the python way”. At the bottom you will find a download link to execute this stuff for yourself.

`l = range(10)`

print l

#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

This is going to be the list (l) we’re working on.

What we’ll be looking at first, is iterating through this list and applying a function. And what simpler function could there be, than the identity?

`a = map(lambda x: x, l)`

b = list(x for x in l)

print a, b

#[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

If you don’t really know what the we did in (a) you may want to read up on lambda expressions, a topic I am not covering now. We need the list-method in (b) because map() always returns a list and the for-expression coughs up a generator object which we have to fully evaluate and convert to a list, to get the equivalent. Generator objects I will cover in the future. For now, suffice to say, it has a reason we are applying the list-function.

Next, we are doing an actual calculation by looking for the cubes of our list (l)

`a = map(lambda x: x**2, l)`

b = list(x**2 for x in l)

print a, b

#[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

Of course you can use actual functions like the cube root or any user defined function.

`def usr(p):`

return p+p

a = map(lambda x: usr(x), l)

b = list(usr(x) for x in l)

#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

We could also combine various functions to create a new anonymous function to apply to our list

`a = map(lambda x: usr(x)+5, l)`

b = list(usr(x)+5 for x in l)

#[5, 7, 9, 11, 13, 15, 17, 19, 21, 23]

I think you got the idea. Remember, (a) and (b) are equivalent.

Next we will use two inputs. Let’s get ourselves another list then, shall we?

`m = range(10,20)`

#[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

And we add both lists together

`a = map(lambda x,y: x+y, l, m)`

b = list(x+y for x,y in zip(l, m))

print a,b

#[10, 12, 14, 16, 18, 20, 22, 24, 26, 28]

Why internally those constructs do something very different, I will cover in the article about generators. But the resulting list is completely the same. Zip() takes lists/iterables as input and convertes them to a list of tuples (n-tuples for n = [number of input iterables]). This tuple is taken apart and put into x and y.

And we can also look at other methods like filter

`a = filter(lambda x: x%2==0, l)`

b = list(x for x in l if x%2==0)

#[0, 2, 4, 6, 8]

filter() can only filter through input. If you want to apply apply a function, you will have to use map again. In (b) you can do that intuitively:

`a = map(lambda x: x*2, filter(lambda x: x%2==0, l))`

b = list(x*2 for x in l if x%2==0)

print a,b

#[0, 4, 8, 12, 16]

As we can see, the for-construct can apply map() and filter()

reduce, which applies a two-parameter-function accumulatively throughout an iterable, on the other hand, is looks a bit different on converting (we try to find out the sum of l):

`a = reduce(lambda x,y: x+y, l, 0)`

b = 0

for x in l:

b = b+x

#45

If we use for in this way, we also can use the filter-if and the map, but we can not use it in the same line as the for-construct. But it is rather trivial, where to use it.

`a = reduce(lambda x,y: x+y, map(lambda x: x*2, filter(lambda x: x%2==0, l)), 0)`

b = 0

for x in l:

if (x%2==0):

b = b+ x*2

#40

In some cases map, filter, and reduce, (together with lambda expressions) probably are syntactic sugar. But in most cases, the python way looks much more readable.

As a note: you can use map, filter and reduce without lambda, as long as you have a function that has as many parameters as you have input iterables. This is valid and does the same as the one far above:

`a = map(usr, l)`

#[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

And if you do not want to think about lambdas you can easily create named functions with this simple rule:

`lambda arguments: expression`

#is the same as

def name(arguments):

return expression

As a final note: The for-construct actually is a generator expression which are handled a bit differently from lists or other “normal” iterables. This can have impact on execution speed (or control flow in general) but that will be covered later.

Thanks for reading.

Attachment: lambda_anon.txt which I couldn’t name .py because WordPress is paranoid.