如何 return 集合扩展中的空子序列

How to return an empty SubSequence in a Collection extension

我正在创建 Collection 的扩展,return 是 SubSequence。但是,如果函数的条件无效,我想 return 一个空的 SubSequence 而不是 nil.

如何在 Collection 的扩展中 return 空 SubSequence

// basic example:
extension Collection {

   func myFunction(condition: Bool) -> SubSequence {
      guard condition else {
          return *EmptySubSequence*
      }
      ...
   }

}

如果我只是对具体类型进行扩展,这将非常容易,但在我将扩展限制为特定类型之前,我想知道它是否可以应用于 Collection 本身。

我发现的最好的是 prefix(0) 将 return 长度为 0 的 SubSequence

如果您需要初始化一个空集合,您应该扩展 RangeReplaceableCollection 而不是 CollectionRangeReplaceableCollection 要求符合它的类型实现空初始化器。


extension RangeReplaceableCollection {
    func myFunction(condition: Bool) -> SubSequence {
        guard condition else {
            return .init()
        }
        // ...
    }
}

虽然我相信 Leo 的回答很有帮助,但我不会在这种情况下使用它。不需要增加RangeReplaceableCollection这样的额外需求,它也增加了replaceSubrange的需求。添加这些要求会限制扩展超出需要。例如,Range 不是 RangeReplaceableCollection。 (如果你真的只打算在 Array 上调用它,那么我建议明确说明并忘记 Collection。)

创建一个“新的”子序列意味着它变得与原始集合无关,并且破坏了索引的含义。调用 init 将创建具有“类似零”起始索引的内容,该索引可能与您正在处理的集合不兼容。您无法安全地比较来自不同集合的索引,即使是相同类型的索引也是如此。

Sweeper 的建议 prefix(0) 更好,但我认为锚定到开头对于需要它的常见算法没有帮助。

相反,我建议在集合的末尾添加一个子序列:self[endIndex...]

考虑 myFunction 的算法,该算法处理集合的某些部分,可能会跳过某些部分,并返回第一个“重要”部分(即跳过空白的分词器的第一阶段)。 endIndex 自然会告诉您它上次查看的位置,并允许您从该位置开始下一次搜索。从此集合 返回空子序列 意味着索引始终兼容。您始终可以安全地设置 startSearchingFrom = result.endIndex,即使它是空的。

在大多数情况下,正确设置索引并不重要。但在大多数情况下,您可能只是想在 Array 上使用它,它不需要是通用的。如果你想让它成为通用的,IMO 你应该确保保留你正在处理的类型的所有语义,这意味着让索引正确。