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)))
精彩评论