相当于python中的Haskell scanl

2024-10-01 15:40:22 发布

您现在位置:Python中文网/ 问答频道 /正文

我想知道python中是否有一个内置函数用于等价的Haskellscanl,因为reduce是{}的等价物。在

这样做的东西:

Prelude> scanl (+) 0 [1 ..10]
[0,1,3,6,10,15,21,28,36,45,55]

问题不在于如何实现它,我已经有2个实现,如下所示(但是,如果你有一个更优雅的实现,请随意在这里展示)。在

首次实施:

^{pr2}$

给出:

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]

第二次实施:

 # 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))

给出:

[0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55]

谢谢:)


Tags: 函数anreducebaseres内置accusing
3条回答

我也有类似的需求。这个版本使用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))

给出:

^{2}$

Python 3.8开始,引入了assignment expressions (PEP 572):=运算符),可以命名表达式的结果,我们可以使用列表理解来复制左扫描操作:

acc = 0
scanned = [acc := acc + x for x in [1, 2, 3, 4, 5]]
# scanned = [1, 3, 6, 10, 15]

或者以一般的方式,给定一个列表、一个约化函数和一个初始化的累加器:

^{2}$

我们可以从左边扫描items,并用f减少它们:

scanned = [accumulator := f(accumulator, x) for x in items]
# scanned = [1, 3, 6, 10, 15]

你可以用这个,如果它更优雅的话:

def scanl(f, base, l):
    for x in l:
        base = f(base, x)
        yield base

使用方式如下:

^{2}$

python3.x有^{}。具体实施如下。实施过程可能会给你一些想法:

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

相关问题 更多 >

    热门问题