在 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 的代码必须知道他们需要哪些索引(通常他们只想要全套结果,或 first
或 others
)
之一
所以无论如何,考虑到这一点,对我来说添加我的 others
计算的 属性 的最佳方法是什么?
如果您对 others
只是一个序列感到满意(所以会支持 for…in
、map
、filter
等),您可以这样做:
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) }
。即使您的实施保证至少有一个条目,一致性也可能是值得的。
好的,所以我有一个 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 的代码必须知道他们需要哪些索引(通常他们只想要全套结果,或 first
或 others
)
所以无论如何,考虑到这一点,对我来说添加我的 others
计算的 属性 的最佳方法是什么?
如果您对 others
只是一个序列感到满意(所以会支持 for…in
、map
、filter
等),您可以这样做:
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) }
。即使您的实施保证至少有一个条目,一致性也可能是值得的。