What is the 'pythonic' equivalent to the 'fold' function from functional programming?

后端 未结 9 2013
被撕碎了的回忆
被撕碎了的回忆 2020-12-01 00:03

What is the most idiomatic way to achieve something like the following, in Haskell:

foldl (+) 0 [1,2,3,4,5]
--> 15

Or its equivalent in

相关标签:
9条回答
  • 2020-12-01 00:25

    The Pythonic way of summing an array is using sum. For other purposes, you can sometimes use some combination of reduce (from the functools module) and the operator module, e.g.:

    def product(xs):
        return reduce(operator.mul, xs, 1)
    

    Be aware that reduce is actually a foldl, in Haskell terms. There is no special syntax to perform folds, there's no builtin foldr, and actually using reduce with non-associative operators is considered bad style.

    Using higher-order functions is quite pythonic; it makes good use of Python's principle that everything is an object, including functions and classes. You are right that lambdas are frowned upon by some Pythonistas, but mostly because they tend not to be very readable when they get complex.

    0 讨论(0)
  • 2020-12-01 00:28

    Starting Python 3.8, and the introduction of assignment expressions (PEP 572) (:= operator), which gives the possibility to name the result of an expression, we can use a list comprehension to replicate what other languages call fold/foldleft/reduce operations:

    Given a list, a reducing function and an accumulator:

    items = [1, 2, 3, 4, 5]
    f = lambda acc, x: acc * x
    accumulator = 1
    

    we can fold items with f in order to obtain the resulting accumulation:

    [accumulator := f(accumulator, x) for x in items]
    # accumulator = 120
    

    or in a condensed formed:

    acc = 1; [acc := acc * x for x in [1, 2, 3, 4, 5]]
    # acc = 120
    

    Note that this is actually also a "scanleft" operation as the result of the list comprehension represents the state of the accumulation at each step:

    acc = 1
    scanned = [acc := acc * x for x in [1, 2, 3, 4, 5]]
    # scanned = [1, 2, 6, 24, 120]
    # acc = 120
    
    0 讨论(0)
  • 2020-12-01 00:28

    The actual answer to this (reduce) problem is: Just use a loop!

    initial_value = 0
    for x in the_list:
        initial_value += x #or any function.
    

    This will be faster than a reduce and things like PyPy can optimize loops like that.

    BTW, the sum case should be solved with the sum function

    0 讨论(0)
提交回复
热议问题