Reputation: 11
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 list, 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.
Upvotes: 0
Views: 4646
Reputation: 1
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)))
Upvotes: 0
Reputation: 46892
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:
(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'])
Upvotes: 2
Reputation: 27585
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
Upvotes: 0
Reputation: 229914
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)
Upvotes: 1
Reputation: 27266
>>> 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 :).
Upvotes: 2
Reputation: 817208
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.
Upvotes: 6
Reputation: 222428
>>> l
[1, 'apple', 2, 'apple', 'apple']
>>> reduce(lambda x, y: x + (1 if y == 'apple' else 0), l, 0)
3
Upvotes: 2