我可以按如下方式编写迭代器:
enum Stage { case a, ab, end }
struct SetMaker<Input: Hashable>: Sequence, IteratorProtocol {
var a,b: Input
var stage = Stage.a
init(a: Input, b: Input) {
self.a = a
self.b = b
}
mutating func next() -> Set<Input>? {
switch stage {
case .a: stage = .ab; return Set<Input>([a])
case .ab: stage = .end; return Set<Input>([a,b])
case .end: return nil
}
}
}
let setMaker = SetMaker(a: "A", b: "B")
for x in setMaker {
print(x)
}
struct ArrayMaker<Input: Hashable>: Sequence, IteratorProtocol {
var a: Input
var b: Input
var stage = Stage.a
init(a: Input, b: Input) {
self.a = a
self.b = b
}
mutating func next() -> Array<Input>? {
switch stage {
case .a: stage = .ab; return Array<Input>([a])
case .ab: stage = .end; return Array<Input>([a,b])
case .end: return nil
}
}
}
let arrayMaker = ArrayMaker(a: "A", b: "B")
for x in arrayMaker {
print(x)
}
第一个返回集合序列,第二个返回数组序列。
这些都工作得很好,但我喜欢让我的代码保持“DRY”(即不要重复自己)。
所以我想写一些通用的东西来允许构建其中任何一个。 我的尝试是:
struct AnyMaker<Input: Hashable, CollectionType>: Sequence, IteratorProtocol {
var a,b: Input
var stage = Stage.a
init(a: Input, b: Input) {
self.a = a
self.b = b
}
mutating func next() -> CollectionType<Input>? {
switch stage {
case .a: stage = .ab; return CollectionType<Input>([a])
case .ab: stage = .end; return CollectionType<Input>([a,b])
case .end: return nil
}
}
}
但这不能编译。 任何帮助表示赞赏:-)
编辑...
@Rob 提出了一个很好的建议,这让我能够部分实现 - 请参阅他的答案。 但如果我有时希望 Collection 成为一个 Set,那么就会出现问题,因为 Set 不是 RangeReplaceable。
换句话说,我创建了一段略有不同的代码:
struct Pairs<C>: Sequence, IteratorProtocol
where C: RangeReplaceableCollection {
var collection: C
var index: C.Index
init(_ collection: C) {
self.collection = collection
index = self.collection.startIndex
}
mutating func next() -> C? {
guard index < collection.endIndex else { return nil }
let element1 = collection[index]
index = collection.index(after: index)
guard index < collection.endIndex else { return nil }
let element2 = collection[index]
let pair = [element1,element2]
return C(pair)
}
}
do {
print("Pairs from array")
let array = ["A","B","C"]
let pairs = Pairs(array) //This line is fine
for pair in pairs {
print(pair)
}
}
do {
print("Pairs from set")
let set = Set(["A","B","C"])
let pairs = Pairs(set) // This line causes error
for pair in pairs {
print(pair)
}
}
“letpairs = Pairs(set)”行会生成错误: “参数类型‘Set’不符合预期类型‘RangeReplaceableCollection’”
所以我需要弄清楚如何在不使用 RangeReplaceableCollection 的情况下实例化集合?
最佳答案
您从未限制 CollectionType
的类型,所以 Swift 根本不知道你可以创建一个,更不用说通过传递数组来创建一个了。 Collection
本身不 promise 任何init
方法也可以。我们需要去RangeReplaceableCollection
得到这个:
struct AnyMaker<CollectionType>: Sequence, IteratorProtocol
where CollectionType: RangeReplaceableCollection {
typealias Input = CollectionType.Element
...
}
完成后,next()
看起来像这样:
mutating func next() -> CollectionType? {
switch stage {
case .a: stage = .ab; return CollectionType([a])
case .ab: stage = .end; return CollectionType([a,b])
case .end: return nil
}
}
请注意,这会返回 CollectionType?
不是CollectionType<Input>?
。没有关于 CollectionType
要求它接受一个类型参数,所以我们不能传递一个。即使我们想要它,也无法表达“采用类型参数”,但我们不想要它。 CollectionType
只需要一些Element
,这是 RangeReplaceableCollection
所 promise 的.
let anyMaker = AnyMaker<[String]>(a: "A", b: "B")
for x in arrayMaker {
print(x)
}
完整代码:
struct AnyMaker<CollectionType>: Sequence, IteratorProtocol
where CollectionType: RangeReplaceableCollection {
typealias Input = CollectionType.Element
var a,b: Input
var stage = Stage.a
init(a: Input, b: Input) {
self.a = a
self.b = b
}
mutating func next() -> CollectionType? {
switch stage {
case .a: stage = .ab; return CollectionType([a])
case .ab: stage = .end; return CollectionType([a,b])
case .end: return nil
}
}
}
关于swift - 返回泛型集合的迭代器 - Swift 4.2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53180755/