I would like to know if there is a built in function in python for the equivalent Haskell scanl
, as reduce
is the equivalent of foldl
.
我想知道在python中是否有一个内置函数用于等效的Haskell scanl,因为reduce相当于foldl。
Something that does this:
事情是这样的:
Prelude> scanl (+) 0 [1 ..10]
[0,1,3,6,10,15,21,28,36,45,55]
The question is not about how to implement it, I already have 2 implementations, shown below (however, if you have a more elegant one please feel free to show it here).
问题不在于如何实现它,我已经有两个实现,如下所示(但是,如果您有一个更优雅的实现,请在这里展示)。
First implementation:
第一个实现:
# Inefficient, uses reduce multiple times
def scanl(f, base, l):
ls = [l[0:i] for i in range(1, len(l) + 1)]
return [base] + [reduce(f, x, base) for x in ls]
print scanl(operator.add, 0, range(1, 11))
Gives:
给:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
Second implementation:
第二个实现:
# Efficient, using an accumulator
def scanl2(f, base, l):
res = [base]
acc = base
for x in l:
acc = f(acc, x)
res += [acc]
return res
print scanl2(operator.add, 0, range(1, 11))
Gives:
给:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
Thank you :)
谢谢你:)
3 个解决方案
#1
14
You can use this, if its more elegant:
你可以用这个,如果它更优雅:
def scanl(f, base, l):
for x in l:
base = f(base, x)
yield base
Use it like:
使用它:
import operator
list(scanl(operator.add, 0, range(1,11)))
Python 3.x has itertools.accumulate(iterable, func= operator.add)
. It is implemented as below. The implementation might give you ideas:
Python 3。出现x itertools。积累(iterable,func = operator.add)。实现如下。实施可能会给你一些建议:
def accumulate(iterable, func=operator.add):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
total = next(it)
yield total
for element in it:
total = func(total, element)
yield total
#2
1
I had a similar need. This version uses the python list comprehension
我也有类似的需要。这个版本使用python列表理解
def scanl(data):
'''
returns list of successive reduced values from the list (see haskell foldl)
'''
return [0] + [sum(data[:(k+1)]) for (k,v) in enumerate(data)]
>>> scanl(range(1,11))
gives:
给:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
#3
0
As usual, the Python ecosystem is also overflowing with solutions:
与往常一样,Python生态系统也充满了解决方案:
Toolz has an accumulate capable of taking a user-supplied function as an argument. I tested it with lambda expressions.
工具z有一个累积能力,可以将用户提供的函数作为参数。我用lambda表达式测试了它。
https://github.com/pytoolz/toolz/blob/master/toolz/itertoolz.py
https://github.com/pytoolz/toolz/blob/master/toolz/itertoolz.py
https://pypi.python.org/pypi/toolz
https://pypi.python.org/pypi/toolz
as does more_itertools
more_itertools一样
http://more-itertools.readthedocs.io/en/stable/api.html
http://more-itertools.readthedocs.io/en/stable/api.html
I did not test the version from more-itertools, but it also can take a user-supplied function.
我没有从more itertools中测试这个版本,但是它也可以使用用户提供的函数。
#1
14
You can use this, if its more elegant:
你可以用这个,如果它更优雅:
def scanl(f, base, l):
for x in l:
base = f(base, x)
yield base
Use it like:
使用它:
import operator
list(scanl(operator.add, 0, range(1,11)))
Python 3.x has itertools.accumulate(iterable, func= operator.add)
. It is implemented as below. The implementation might give you ideas:
Python 3。出现x itertools。积累(iterable,func = operator.add)。实现如下。实施可能会给你一些建议:
def accumulate(iterable, func=operator.add):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
total = next(it)
yield total
for element in it:
total = func(total, element)
yield total
#2
1
I had a similar need. This version uses the python list comprehension
我也有类似的需要。这个版本使用python列表理解
def scanl(data):
'''
returns list of successive reduced values from the list (see haskell foldl)
'''
return [0] + [sum(data[:(k+1)]) for (k,v) in enumerate(data)]
>>> scanl(range(1,11))
gives:
给:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]
#3
0
As usual, the Python ecosystem is also overflowing with solutions:
与往常一样,Python生态系统也充满了解决方案:
Toolz has an accumulate capable of taking a user-supplied function as an argument. I tested it with lambda expressions.
工具z有一个累积能力,可以将用户提供的函数作为参数。我用lambda表达式测试了它。
https://github.com/pytoolz/toolz/blob/master/toolz/itertoolz.py
https://github.com/pytoolz/toolz/blob/master/toolz/itertoolz.py
https://pypi.python.org/pypi/toolz
https://pypi.python.org/pypi/toolz
as does more_itertools
more_itertools一样
http://more-itertools.readthedocs.io/en/stable/api.html
http://more-itertools.readthedocs.io/en/stable/api.html
I did not test the version from more-itertools, but it also can take a user-supplied function.
我没有从more itertools中测试这个版本,但是它也可以使用用户提供的函数。