Glen F.
Glen F.

Reputation: 190

Alternating sum of integers in Python using lambda

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

Answers (2)

John La Rooy
John La Rooy

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

inspectorG4dget
inspectorG4dget

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

Related Questions