Reputation: 190
I need to write a simple function in Python that calculates the alternating sum of a list of integers.
Example: [ a1, a2, a3, ...] will be [a1 - a2 + a3 - a4...]
I need to use a lambda function to implement this.
So far I have
print reduce(lambda a,b : ((-a) + b), [10, 20, 30, 40])
which prints out 20; but it should print -20.
What am I doing wrong?
Upvotes: 0
Views: 1232
Reputation: 304375
It's possible to include the cycle in a lambda like this
>>> from itertools import cycle
>>> reduce(lambda a, b, c=cycle((-1, 1)) : a + next(c) * b, [10, 20, 30, 40])
-20
The trick here is that reduce
only passes values to a
and b
. c
is assigned the cycle just once when the function is created
Upvotes: 1
Reputation: 114025
In the case of your lambda function, reduce
works like this:
def myReduce(f, L):
arg1 = L[0]
for arg2 in L[1:]:
arg1 = f(arg1, arg2)
return arg1
As you can see, this will negate the running total every time:
In the first iteration, it computes -10 + 20 = 10
, which then gets stored as arg1
. Then, your lambda is called with the arguments 10
and 30
, which makes it compute -10 + 30 = 20
; so now arg1
takes the value 20
. Finally, the lambda is called with 20
and 40
, which makes it compute -20 + 40 = 20
.
See the problem?
There are several ways by which you can solve this. Here are a few:
L = [10, 20, 30, 40]
sum(map(lambda t : t[0]-t[1], zip(L[::2], L[1::2])))
Or
answer = 0
for i,elem in enumerate(L):
mult = [1,-1][i%2]
answer += elem * mult
Or
mults = itertools.cycle([1,-1])
answer = 0
for elem, mult in zip(L, mults):
answer += elem, mult
Upvotes: 2