开发者

Reduce function in Python

I used the reduce function to multiply all the elements of a list as follows.

l = [1,2,3,4,5]
reduce(lambda x,y:x*y,l) #returns 120

Now, suppose I have a li开发者_开发百科st, l = [1,'apple',2,'apple','apple'], and I want to count how many times the word "apple" appears in the list. Is this possible using reduce?

I'm aware I can use l.count('apple'), but I want to know if a reduce solution is possible.


Yes it is:

reduce(lambda x,y: x + (y == 'apple'), l, 0)

But as you mentioned yourself, there is no need to use reduce here. It is likely that it will be slower than any other counting method and the intention is not immediately clear.


>>> l
[1, 'apple', 2, 'apple', 'apple']
>>> reduce(lambda x, y: x + (1 if y == 'apple' else 0), l, 0)
3


>>> l = [1,'apple',2,'apple','apple']
>>> reduce(lambda s, i: s+1 if i == "apple" else s, l, 0)
3

You can simplify s+1 if i == "apple" else s part to just s + (i == "apple"), but I think implicit bool => int conversions are cryptic. But using reduce for this job is cryptic anyway :).


This is easiest using an initializer (the extra 0 at the end of the call to reduce), so you only need to convert the second argument:

reduce(lambda x, y: x + (1 if y=='apple' else 0), [1,'apple',2,'apple','apple'], 0)

Or you can reduce something that has been transformed by a map into 0 and 1:

reduce(lambda x, y: x+y, map(lambda x: 1 if x=='apple' else 0,  [1,'apple',2,'apple','apple']))

But there are lots of ways to make this more natural:

  • use list comprehensions rather than reduce
  • use the operators package instead of defining your own function for addition
  • user itertools

(And the counter suggestion above is really cool - I don't think I even knew that existed.)

A simpler (but not very efficient) approach would be:

len([x for x in [1,'apple',2,'apple','apple'] if x=='apple'])


If you use a "real" function instead of a lambda function solutions to problems like this usually become much clearer:

def count_apples(acc, v):
   if v == 'apple':
      return acc+1
   else:
      return acc

l = [1,'apple',2,'apple','apple']
print reduce(count_apples, l, 0)


from operator import mul
from time import clock

n= 10000

li = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]

te = clock()
for i in xrange(n):
    x = reduce(mul,li)
print clock()-te


te = clock()
for i in xrange(n):
    y = reduce(lambda a,b: a*b,li)
print clock()-te


print x==y

result

0.0616016840129
0.124420003101
True

.

li = [1,78,2,2,12,45,1,2,8,1,2,5,4,2]


te = clock()
for i in xrange(n):
    x = li.count(2)
print clock()-te

te = clock()
for i in xrange(n):
    y = sum(1 for a in li if a==2)
print clock()-te

te = clock()
for i in xrange(n):
    z = len([a for a in li if a==2])
print clock()-te

print x==y==z

produces

0.0110332458455
0.0428308625817
0.0518741907142
True


Custom reduce function in python

def my_reduce(func,sequence) :
    res=sequence[0]
    for variable in sequence[1:]:
        res =func(variable,res)

    return res


def my_sum(a,b):
    return a+b


seq=[1,2,3,4,5]
print(str(my_reduce(my_sum,seq)))
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜