当前位置: 首页 > 面试题库 >

我们如何创建通用数组扩展来汇总Swift中的数字类型?

东郭子默
2023-03-14
问题内容

Swift可让您创建一个将Integer与之相加的Array扩展:

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

这个问题 不是如何对数字求和 ,而是如何 创建通用数组扩展 来实现。

越来越近

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

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

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,2,3].sum(0) //6
[1.1,2.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,2,3].sum(0) //6

但是在不带参数的情况下无法解析该方法,即:

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

添加Integer到方法签名也无助于方法解析

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

但是希望这将帮助其他人更接近解决方案。

一些进展

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

let i:Int = [1,2,3].sum()
let d:Double = [1.1,2.2,3.3].sum()

问题答案:

从Swift
2开始,可以使用协议扩展来做到这一点。(有关更多信息,请参见Swift编程语言:协议)。

首先,该Addable协议:

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

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

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

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

用法:

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

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


 类似资料:
  • 问题内容: 如何扩展Swift 或带有自定义功能工具的类型? 浏览Swift的API文档可发现Array方法是的扩展,例如: 当复制和粘贴相同的源并尝试任何变体时,例如: 它无法生成并显示以下错误: 标称类型不能扩展 使用完整类型定义失败,即: 并且也无法使用和。 奇怪的是,Swift让我扩展了一个无类型数组: 它让我打电话给: 但是我无法创建适当的泛型类型扩展,因为当类型流过该方法时,该类型似乎

  • 当复制和粘贴相同的源并尝试任何变体时,如: 它无法生成,错误为: 无法扩展标称类型 奇怪的是,Swift让我用以下代码扩展一个非类型化数组: 它让我调用: 但是我不能创建一个合适的泛型类型扩展,因为当类型流经方法时,它似乎丢失了,例如,试图用以下内容替换Swift的内置筛选器:

  • 问题内容: 在目标c中,我可以创建一个类数组并在方法中使用它 但是,swift没有“类”功能。返回类的元类型会导致错误 最后一行导致“致命错误:数组元素无法桥接到Objective-C” 如何在Swift中创建类数组? 问题答案: 显然,此问题已在Beta 3中修复,因此不再需要解决方法 我发现了一个纯粹的Swift hack: 先前的答案 我无法在Swift中以任何方式获取实例。似乎无法直接从转

  • 问题内容: 我正在尝试对Array进行扩展,以允许将可选T的数组转换为非可选T的数组。 例如,这可以写成这样的自由函数: 但是,我无法将此作为扩展。我试图告诉编译器,扩展名仅适用于可选值数组。这是我到目前为止的内容: (它不会编译!) 问题答案: 不可能限制为通用结构或类定义的类型-数组旨在与任何类型一起使用,因此您不能添加适用于类型子集的方法。类型约束只能在声明泛型时指定 实现所需功能的唯一方法

  • 问题内容: 可以说我有: 我想实现allEqual()函数作为扩展,所以我可以做 问题答案: 可以说具体类型是S CollectionType协议

  • 问题内容: 我想使用Accelerate框架扩展[Float]和[Double],但每个框架都需要不同的实现。 我尝试了明显的方法: 并得到这个错误: “必须在具有’where’子句指定约束的非专用泛型’Array’上声明受约束的扩展” 以这种方式在Swift 2中扩展泛型类型是否可行? 我的代码现在可以按预期工作了。这是显示使用Accelerate框架求和的示例。 问题答案: 如果只想扩展特定类