快速运行总和 [英] Swift running sum

查看:21
本文介绍了快速运行总和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个函数 runningSum 在一个数字数组(或任何可添加的有序集合)上返回一个相同长度的数组,其中每个元素 i 是 A 中所有元素的总和,直到包含 i.

I'd like a function runningSum on an array of numbers a (or any ordered collection of addable things) that returns an array of the same length where each element i is the sum of all elements in A up to an including i.

示例:

runningSum([1,1,1,1,1,1]) -> [1,2,3,4,5,6]
runningSum([2,2,2,2,2,2]) -> [2,4,6,8,10,12]
runningSum([1,0,1,0,1,0]) -> [1,1,2,2,3,3]
runningSum([0,1,0,1,0,1]) -> [0,1,1,2,2,3]

我可以使用 for 循环或其他方式来完成此操作.有没有更实用的选择?它有点像reduce,只是它构建了一个包含所有中间值的结果数组.

I can do this with a for loop, or whatever. Is there a more functional option? It's a little like a reduce, except that it builds a result array that has all the intermediate values.

更一般的做法是有一个函数可以接受任何序列并提供一个序列,该序列是输入序列的运行总和.

Even more general would be to have a function that takes any sequence and provides a sequence that's the running total of the input sequence.

推荐答案

您正在寻找的通用组合器通常称为 scan,并且可以根据 reduce 定义(就像列表中的所有高阶函数一样):

The general combinator you're looking for is often called scan, and can be defined (like all higher-order functions on lists) in terms of reduce:

extension Array {
    func scan<T>(initial: T, _ f: (T, Element) -> T) -> [T] {
        return self.reduce([initial], combine: { (listSoFar: [T], next: Element) -> [T] in
            // because we seeded it with a non-empty
            // list, it's easy to prove inductively
            // that this unwrapping can't fail
            let lastElement = listSoFar.last!
            return listSoFar + [f(lastElement, next)]
        })
    }
}

(但我建议这不是一个很好的实现.)

(But I would suggest that that's not a very good implementation.)

这是一个非常有用的通用函数,可惜没有包含在标准库中.

This is a very useful general function, and it's a shame that it's not included in the standard library.

然后,您可以通过专门化起始值和操作来生成累积总和:

You can then generate your cumulative sum by specializing the starting value and operation:

let cumSum = els.scan(0, +)

你可以简单地省略零长度的情况:

And you can omit the zero-length case rather simply:

let cumSumTail = els.scan(0, +).dropFirst()

这篇关于快速运行总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆