在 Swift 中定义匿名 CollectionType 的最简单方法

Simplest Way to Define an Anonymous CollectionType in Swift

好的,所以我有一个 class,它是一个包含一组结果的 CollectionType,并且可以像数组一样访问以获取每个结果。

但是,并非所有结果在所有情况下都是相关的,因此有时只需要获取第一个元素,而其他代码可能只想调用附加值。我将尝试用一个例子来说明这一点(请原谅任何基本错误):

class MyClass: CollectionType {
    typealias Index = Int
    let startIndex: Index = 0
    let endIndex: Index

    // Initialiser here (setting self.endIndex)

    func generate() -> IndexingGenerator<MyClass> {
        return IndexingGenerator(self) 
    }

    subscript(theIndex: Index) -> String { /* Get value at given index. */ }

    var first: String { return self[0] }
}

我实际上想做的是创建一个计算的 属性 others,它本身将作为一个集合,但省略了主要结果对象中的第一项,所以我可以做像这样:

let first = myClassInstance.first
for item in myClassInstance.others { /* Do something */ }

我已经大大简化了这个例子,所以不,恐怕我不能只将 first 存储为 属性 或以某种方式将结果分开;结果在整体上都是相关的,而且在上面的分离格式中也适用于不同的目的,我想避免使用这个 class 的代码必须知道他们需要哪些索引(通常他们只想要全套结果,或 firstothers)

之一

所以无论如何,考虑到这一点,对我来说添加我的 others 计算的 属性 的最佳方法是什么?

如果您对 others 只是一个序列感到满意(所以会支持 for…inmapfilter 等),您可以这样做:

class MyClass: CollectionType {
    var others: SequenceOf<String> {
        return SequenceOf { ()->GeneratorOf<String> in
            var g = self.generate()
            // the following fiddlyness courtesy of the requirement
            // not to call .next() a second time after it returns nil...
            if g.next() != nil {
                return GeneratorOf { g.next() }
            }
            else {
                return GeneratorOf { nil }
            }
        }
    }
}

let mc = MyClass()
for item in mc.others {
    println(item)
}

根据您保存内部数据的方式,您可以通过 return 使用内部数据切片的生成器来大大简化它。

如果您想要的东西 return 是一个集合而不仅仅是一个序列,请考虑让您的集合符合 Sliceable。然后你可以使用 dropFirst(self).

P.S。为了与 Swift std lib 的其余部分保持一致,您应该考虑将 first return 作为空集合的可选项:var first: String? { return Swift.first(self) }。即使您的实施保证至少有一个条目,一致性也可能是值得的。