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

前端之家收集整理的这篇文章主要介绍了我们如何创建一个通用的数组扩展,它与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"

猜你在找的Swift相关文章