xxbidiao
xxbidiao

Reputation: 874

simplifying and improving performance of chained lambda expression in python

I have just started writing lambdas in python these days and I wonder whether there's a good way to avoid chaining map/reduce/filter (which causes confusion when closing parenthesis).

Here's a lambda which chains a few level:

a = [1,2,3,4,5,6]
b = [1,0,0,1,0,1]
reduce(lambda x,y:x+y,map(lambda x:a[x],map(lambda x:x[0],filter(lambda (i,x):x==0,enumerate(b))))) # returns 10,2+3+5 where corresponding elements in array b is 0

I still prefer old-school style of OOP like

x.dosomething().doanotherthing().dofoo().dobar()

which make things easier to read for me. Besides defining these as other function variable which causes intermediate results to be calculated, are there any inline ways (that avoid intermediate results to be calculated). How can I do this?

Upvotes: 0

Views: 210

Answers (3)

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48067

You may use itertools.compress() which is specifically made for this kind of filtering. For example:

>>> from itertools import compress

>>> list(compress(a, b))
[1, 4, 6]

But this filters the number corresponding to 1 in b. So firstly you need to flip the value in b. Hence your solution will be as:

>>> flipped_b = [not i for i in b]
>>> sum(compress(a, flipped_b))
10

# OR, you may do:
>>> sum(a) - sum(compress(a, b))
10

Upvotes: 4

shx2
shx2

Reputation: 64318

List comprehensions (and generator expressions) are preferable over map/filter/reduce. Also, if you need the sum of some elements, use sum(), not reduce().

In your case, zip is also useful.

How about this?

sum([ x for x,y in zip(a,b) if y==0 ])

Upvotes: 1

zvone
zvone

Reputation: 19352

I would say it is better not to use reduce, filter and map, because they reduce readibility of the code. Use simpler functions and list comprehensions instead.

So:

  1. instead of reduce(lambda x,y: x+y, something), do sum(something)
  2. instead of filter(lambda i,x: x==0, enumerate(b)), do [(i,x) for i,x in enumerate(b) if x==0]
  3. instead of map(lambda x:x[0], something), do [x[0] for x in something]

In the end, after some optimizations, the whole thing becomes the much more readable:

sum(a[i] for i,x in enumerate(b) if x==0)

Upvotes: 3

Related Questions