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

时间:2015-01-25 14:34:55

标签: swift collections

好的,所以我有一个包含一组结果的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成为一个存储的属性,或者以某种方式将结果分开;结果既是完整的,也是上面分离的格式,用于不同的目的,我想避免代码使用这个类必须知道他们需要哪些索引(通常他们只需要全套结果,或firstothers)之一

所以,无论如何,考虑到这一点,我最好的方法是添加others计算属性?

1 个答案:

答案 0 :(得分:1)

如果您对others只是一个序列感到满意(那么支持for…inmapfilter等),您可以这样做:< / p>

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)
}

根据您保存内部数据的方式,您可以通过返回内部数据片段的生成器来简化这一过程。

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

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