我们如何创建一个通用的数组扩展,它与Swift中的Number类型相加?

Swift允许您创建一个Array扩展,将Integer与:
extension Array {
    func sum() -> Int {
        return self.map { $0 as Int }.reduce(0) { $0 + $1 }
    }
}

现在可以用它来汇总Int [],如:

[1,2,3].sum() //6

但是,我们如何制作一个通用版本来支持其他Number类型,例如Double []呢?

[1.1,2.1,3.1].sum() //fails

这个问题不是如何计算数字,而是如何创建一个通用的Array Extension来实现。

越来越近

这是最接近我能够得到的,如果它帮助任何人更接近解决方案:

您可以创建一个可以满足我们所需要做的协议,即:

protocol Addable {
    func +(lhs: Self,rhs: Self) -> Self
    init()
}

然后扩展我们要支持的每个类型符合上述协议:

extension Int : Addable {
}

extension Double : Addable {
}

然后添加一个扩展与该约束:

extension Array {
    func sum<T : Addable>(min:T) -> T
    {
        return self.map { $0 as T }.reduce(min) { $0 + $1 }
    }
}

现在可以针对我们扩展以支持协议的数字,即:

[1,3].sum(0) //6
[1.1,3.1].sum(0.0) //6.3

不幸的是,我没有得到它的工作,而不必提供一个参数,即:

func sum<T : Addable>(x:T...) -> T?
{
    return self.map { $0 as T }.reduce(T()) { $0 + $1 }
}

修改后的方法仍然可以使用1个参数:

[1,3].sum(0) //6

但无法解析方法调用它没有参数,即:

[1,3].sum() //Could not find member 'sum'

为方法签名添加整数也无法解决方法:

func sum<T where T : Integer,T: Addable>() -> T?
{
    return self.map { $0 as T }.reduce(T()) { $0 + $1 }
}

但希望这将有助于其他人更加接近解决方案。

一些进展

从@GabrielePetronella答案看,我们可以调用上述方法,如果我们在调用站点上明确指定类型,如:

let i:Int = [1,3].sum()
let d:Double = [1.1,2.2,3.3].sum()
从Swift 2开始,可以使用协议扩展来做到这一点。 (详见 The Swift Programming Language: Protocols)。

首先,Addable协议:

protocol Addable: IntegerLiteralConvertible {
    func + (lhs: Self,rhs: Self) -> Self
}

extension Int   : Addable {}
extension Double: Addable {}
// ...

接下来,扩展SequenceType以添加可添加元素的序列:

extension SequenceType where Generator.Element: Addable {
    var sum: Generator.Element {
        return reduce(0,combine: +)
    }
}

用法:

let ints = [0,1,3]
print(ints.sum) // Prints: "6"

let doubles = [0.0,1.0,2.0,3.0]
print(doubles.sum) // Prints: "6.0"

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...