如何 return Swift 中的通用集合或迭代器?

How to return a generic collection or iterator in Swift?

我正在尝试做这样的事情:

func fullOrSubarray(array: [Int]) -> ReturnType {
    return array.count < 10 ? array : array[0..<10]
}

当我尝试 return Array<Int>ArraySlice<Int> 时,我应该将什么写入 ReturnType

我知道我可以简单地将 ArraySlice<Int> 转换为 Array<Int>(反之亦然),但出于性能原因我不想这样做。我想要 return 一些通用集合或迭代器类型,但 Swift 似乎没有。我是否必须为这样的事情编写自定义迭代器?其他语言有各种通用迭代器,所以我可以 return 数组、集合等互换。

您描述的情况是有可能发生的,但首先,您应该看看是否可以避免。您给出的具体示例正是 prefix 并且绝对应该实现为:

func fullOrSubarray(array: [Int]) -> ArraySlice<Int> {
    array.prefix(10)
}

这里 return 正确的是 ArraySlice。没有理由 return 其他东西。查看 implementation of prefix 以了解 stdlib 如何处理此问题。

也就是说,在极少数情况下,执行您所描述的操作可能会有用。例如,底层数据可能位于 Set 或 Array 中,您希望避免副本。在这种情况下,正确的工具是 AnySequence 或 AnyCollection:

func fullOrSubarray(array: [Int]) -> AnySequence<Int> {
    array.count < 10 ? AnySequence(array) : AnySequence(array[0..<10])
}

但这是一种非常不寻常的情况,永远不会用于 Array 和 ArraySlice。为此,只需使用 ArraySlice,或转换回 Array。不要假设从切片到数组的转换很昂贵。 stdlib 在内部写时复制数组缓冲区方面非常聪明,通常可以避免制作任何副本。

即使在数据当前可能是一个集合的情况下,除非它非常大或经常访问,通常最好在 return 将其转换为数组之前将其转换为数组。如果它经常作为数组访问,我倾向于首先将其存储为数组而不是集合。

但如果所有这些都让您失望,并且您需要 return 一个未知的序列类型,这就是 AnySequence(或 AnyCollection)的用途。