user3398633
user3398633

Reputation:

Python one-line sum implementation?

First of all, I ask this question by pure curiosity to see some great one-liners skills. The sum() function remains the best function to sum objects in a list.

But as said, I ask by pure curiosity: Is there a way to sum objects from a list (obviously, without using sum()) in one line? Let's say the list would be range(0, 100)

I have absolutely no idea how this could be achieved, but as Python is really great and flexible, so I have no doubt it is possible.

Upvotes: 2

Views: 5216

Answers (3)

MSeifert
MSeifert

Reputation: 152810

Python may not be the best language for recursive approaches because (1) it doesn't support tail-recursion (2) function calls are really expensive (3) the recursion limit prevents deep recursions and (4) slicing sequences scales with O(n) (where n is the number of elements in the slice).

However you can use them for one-liners!

One approach would be just to successivly pop and add the first element until the sequence is exhausted:

>>> sum_func = lambda x: x[0] + sum_func(x[1:]) if x else 0
>>> sum_func(range(100))
4950

The first part is triggered as long as if x (that is to say x is not empty). This approach shows all the shortcomings of using recusion in Python: It hits the recursion limit for sequences of length ~300, it scales with O(n**2) and it's really slow compared to the built-in sum and reduce approach.

One can mitigate one of the disadvantages by using a divide-and-conquer recursion approach:

>>> sum_func = lambda x: sum_func(x[:len(x)//2]) + sum_func(x[len(x)//2:]) if len(x) > 1 else x[0]
>>> sum_func(range(100))
4950

This time it recurses on both halfs of the list, thereby reducing the recusion depth from n to log2(n), so it can handle even longer sequences. However it's not faster than the one above.


And of course there's always the cheat option:

>>> from numpy import sum
>>> sum(range(100))
4950

In case you really want it really fast :-)

Upvotes: 1

Kevin
Kevin

Reputation: 76254

Just for fun, here's a solution that needs no no built-in functions at all. It's basically a reimplentation of reduce, using a bit of lambda magic.

>>>>(lambda f: lambda *args: f(f, *args))(lambda self, f, seq, d: d if not seq else f(seq[0], self(self, f, seq[1:], d)))(lambda a,b: a+b, range(100), 0)
4950

Upvotes: 1

jonrsharpe
jonrsharpe

Reputation: 122154

You can take a functional approach, using reduce and an addition function (e.g. a lamdba expression or operator.add):

>>> from operator import add
>>> reduce(add, range(0, 100))
4950

(Note that in 3.x you need to from functools import reduce first.)

Per the documentation, reduce(function, iterable) will

Apply function of two arguments cumulatively to the items of iterable, from left to right, so as to reduce the iterable to a single value.

Upvotes: 5

Related Questions