是否有一种优雅的方式(想想单行)来获取Swift中SequenceType
的前n个元素?
我当然可以编写一个在n个元素之后终止的for循环,但这有点笨重。
另请注意,解决方案应该能够处理无限序列。
答案 0 :(得分:13)
这不正是mySequence.prefix(numberOfElements)
的作用吗?
答案 1 :(得分:2)
在Swift 2中,您可以将其创建为扩展名:
extension SequenceType {
func take(n: Int) -> [Generator.Element] {
var result: [Generator.Element] = []
var g = self.generate()
for _ in 1...n {
if let next = g.next() {
result.append(next)
} else {
break
}
}
return result
}
}
在Swift 1中,它必须写成函数:
func take<Seq: SequenceType>(n: Int, xs: Seq) -> [Seq.Generator.Element] {
var result: [Seq.Generator.Element] = []
var g = xs.generate()
for _ in 1...n {
if let next = g.next() {
result.append(next)
} else {
break
}
}
return result
}
请注意,在任何一种情况下,SequenceType
都没有指定如果您多次调用generate()
会发生什么。它可以返回相同的值(如Array
中所示)。它可以返回不同的值(如在音频数据流中)。它根本不会返回任何东西。因此,take()
的来电者可能需要一些关于其对序列影响的特殊知识。
答案 2 :(得分:0)
SequenceType
仅支持generate()
。也许更“快速”的方法是定义一个Generator
给定一个开始和结束索引,一个'基础'生成器将跳过第一个元素,开始返回一些,然后在结束索引后停止。像这样:
struct SubscriptGenerator<Base: GeneratorType> : GeneratorType {
var nowIndex : Int = 0
let endIndex : Int
let begIndex : Int
var generator : Base
init (generator: Base, startIndex: Int, endIndex: Int) {
precondition(startIndex < endIndex, "oops")
self.generator = generator
self.endIndex = endIndex
self.begIndex = startIndex
}
// MARK - GeneratorType
typealias Element = Base.Element
mutating func next() -> Element? {
while (nowIndex < begIndex) { nowIndex++; generator.next () }
return nowIndex++ < endIndex ? generator.next() : nil
}
}
这只是一个例子。可以定义一个convenience init()
来获取SequenceType
并生成基本生成器。在行动:
75> var gen = [10,20,30,40,50].generate()
76> var sg = SubscriptGenerator(generator: gen, startIndex: 1, endIndex:3)
sg: SubscriptGenerator<IndexingGenerator<[Int]>> = { ... }
77> sg.next()
$R2: Int? = 20
78> sg.next()
$R3: Int? = 30
79> sg.next()
$R4: Int? = nil
有关示例,请参阅Swift的EnumerateGenerator
。
注意:可能是Swift功能的Stride
关系可以做你想要的。
答案 3 :(得分:-1)
为什么不
var seq = NominalSequence().generate()
var a = (0..<10).map({_ in seq.next()!})
两行,但是功能性的。