6

In python we can sum a list as: sum(list_of_integers).

Now sum is just an operation among two elements with the operator +.

What if I want to sum a list with different operator like or, and, xor etc?

I could do it manually one by one using a for loop, but there must be a better way.

Vikas Periyadath
  • 3,088
  • 1
  • 21
  • 33
mourinho
  • 763
  • 6
  • 13
  • 24

2 Answers2

9

functools.reduce is perfect for this use-case. It takes a function to apply to the accumulated value and the next value, the iterable you want to reduce, and optionally an initialiser.

For example, bitwise-or-ing every value in a list:

import functools

functools.reduce(lambda a, b: a ^ b, [1, 2, 3])

This is equivalent to 1 ^ 2 ^ 3.

Christian Scott
  • 893
  • 7
  • 19
  • but reduce is not built-in in python anyway without importing any library..thanks – mourinho Feb 15 '18 at 08:02
  • 3
    Not using the standard library seems like an extremely arbitrary restriction. Is this for homework? – Christian Scott Feb 15 '18 at 08:06
  • 5
    @mourinho `reduce` *used* to be part of the `builtins` module in Python 2, but it was relegated to `functools` because, well, [Guido just doesn't like it](https://stackoverflow.com/questions/181543/what-is-the-problem-with-reduce). Not wanting to use core libraries seems like an artificial restriction. Otherwise, note, Guido recommends a for-loop. And that seems like the most straightforward way if you don't want `reduce` – juanpa.arrivillaga Feb 15 '18 at 08:09
  • @mourinho Then you should've mentioned that in the question. There's no reason not to use the standard library – jamylak Feb 15 '18 at 08:40
5

The alternative to functools.reduce is to write an explicit for loop:

def xor_reduce(args):
    result = 0
    for x in args:
        result ^= x
    return result

xor_reduce([1, 2, 3])

If you are going for the reduce way (not so unreasonable for this, IMO), I would make use of the operator module:

from functools import reduce
from operator import xor

reduce(xor, [1, 2, 3])

The operator module (which is in the standard library and should therefore always be available) also defines all other standard operations as functions, but for or and and a trailing _ is added because they are reserved keywords:

from operator import or_, and_
reduce(or_, [1, 2, 3])
reduce(and_, [1, 2, 3])

Although for these two you could use the built-in functions any and all:

any([1, 2, 3])
all([1, 2, 3])
Graipher
  • 6,891
  • 27
  • 47
  • 1
    This is much better than the accepted answer, showing a manual and the `reduce` way to do it. Absolutely no need for a `lambda`. Faster and more elegant – jamylak Feb 15 '18 at 08:41