如何访问 Swift 字典中的下一个键?
How to access the next key in a Swift dictionary?
我有这个代码
for (k, v) in myDict {
println(k)
}
如何访问字典中的下一个键(例如 myDict[k + 1])?
提前致谢!
没有"the next key";字典没有顺序。
但是,由于您正在遍历字典...
for (k, v) in myDict {
println(k)
}
我假设你的意思是:我怎么知道,在 this 迭代中,k
会在 下一个次迭代?
一个简单的解决方案是将字典强制转换为一个数组(键值元组):
let arr = Array(myDict)
现在你有了整数索引。所以你可以这样枚举它:
let arr = Array(myDict)
for (ix, (k,v)) in enumerate(arr) {
println("This key is \(k)")
if ix < arr.count-1 {
println("The next key is \(arr[ix+1].0)")
}
}
事实当然是,您 可以 直接枚举字典,但索引不是整数,因此使用起来有点困难。 Martin R 也展示了一种方法来说明这一点。
我不知道这是否是您要找的,但您可以
以 "similar" 的方式遍历字典作为迭代
通过使用 DictionaryIndex<Key, Value>
作为索引的数组:
let dict = [ "foo" : 1, "bar" : 2, "baz" : 3]
for idx in indices(dict) {
let (k, v) = dict[idx]
println("Current key: \(k), current value: \(v)")
let nextIdx = idx.successor()
if nextIdx != dict.endIndex {
let (k1, v1) = dict[nextIdx]
println("Next key: \(k1), next value: \(v1)")
}
}
示例输出:
Current key: bar, current value: 2
Next key: baz, next value: 3
Current key: baz, current value: 3
Next key: foo, next value: 1
Current key: foo, current value: 1
一种可能的解决方案是创建 Generator
,其中 return 是序列中的当前值和先前值。为此,您需要一个自定义 Generator
,它将 return 一个元组,其中包含序列中的先前值和当前值,来自 next
:
struct PairGenerator<Base: GeneratorType> : GeneratorType {
typealias ElementPair = (previousElement: Base.Element, currentElement: Base.Element)
private var base: Base
private var previousElement: Base.Element?
init(_ base: Base) {
self.base = base
}
mutating func next() -> ElementPair? {
if previousElement == nil { previousElement = base.next() }
let currentElement = base.next()
// Since `base.next()` returns `nil` when the end of the sequence
// is reached, we need to check `previousElement` and `currentElement `
// aren't `nil`. If either of them are, `nil` will be returned to signal
// there aren't any pairs left.
if let prev = previousElement, curr = currentElement {
previousElement = currentElement
return (prev, curr)
}
return nil
}
}
然后将PairGenerator
存入一个PairSequence
,符合SequenceType
;这意味着您可以在 for
循环中对其进行迭代。
struct PairSequence<Base: SequenceType> : SequenceType {
let generator: PairGenerator<Base.Generator>
init(_ base: Base) {
generator = PairGenerator(base.generate())
}
func generate() -> PairGenerator<Base.Generator> {
return generator
}
}
现在您需要一个函数,它将从符合 SequenceType
:
的对象创建 PairSequence
func pairs<Seq: SequenceType>(base: Seq) -> PairSequence<Seq> {
return PairSequence(base)
}
最后,你可以这样使用:
let myDict = ["1": 1, "2": 2, "3": 3, "4": 4]
let values = Array(myDict.values).sorted(<)
for (prev, curr) in pairs(values) {
println("\(prev), \(curr)")
}
// Prints:
// 1, 2
// 2, 3
// 3, 4
您可以使用 pairs(myDict)
,但就像@Martin R 和@matt 所说的那样 - 词典没有顺序,因此您可能无法按照预期的顺序获得结果。
有关 SequenceType
和 GeneratorType
的更多信息,我建议查看 Playing With Swift and Generators In Swift。
或者,正如@Martin R 在他的评论中指出的那样,您可以使用:
for (prev, curr) in zip(values, dropFirst(values)) {
println("\(prev), \(curr)")
}
我有这个代码
for (k, v) in myDict {
println(k)
}
如何访问字典中的下一个键(例如 myDict[k + 1])?
提前致谢!
没有"the next key";字典没有顺序。
但是,由于您正在遍历字典...
for (k, v) in myDict {
println(k)
}
我假设你的意思是:我怎么知道,在 this 迭代中,k
会在 下一个次迭代?
一个简单的解决方案是将字典强制转换为一个数组(键值元组):
let arr = Array(myDict)
现在你有了整数索引。所以你可以这样枚举它:
let arr = Array(myDict)
for (ix, (k,v)) in enumerate(arr) {
println("This key is \(k)")
if ix < arr.count-1 {
println("The next key is \(arr[ix+1].0)")
}
}
事实当然是,您 可以 直接枚举字典,但索引不是整数,因此使用起来有点困难。 Martin R 也展示了一种方法来说明这一点。
我不知道这是否是您要找的,但您可以
以 "similar" 的方式遍历字典作为迭代
通过使用 DictionaryIndex<Key, Value>
作为索引的数组:
let dict = [ "foo" : 1, "bar" : 2, "baz" : 3]
for idx in indices(dict) {
let (k, v) = dict[idx]
println("Current key: \(k), current value: \(v)")
let nextIdx = idx.successor()
if nextIdx != dict.endIndex {
let (k1, v1) = dict[nextIdx]
println("Next key: \(k1), next value: \(v1)")
}
}
示例输出:
Current key: bar, current value: 2 Next key: baz, next value: 3 Current key: baz, current value: 3 Next key: foo, next value: 1 Current key: foo, current value: 1
一种可能的解决方案是创建 Generator
,其中 return 是序列中的当前值和先前值。为此,您需要一个自定义 Generator
,它将 return 一个元组,其中包含序列中的先前值和当前值,来自 next
:
struct PairGenerator<Base: GeneratorType> : GeneratorType {
typealias ElementPair = (previousElement: Base.Element, currentElement: Base.Element)
private var base: Base
private var previousElement: Base.Element?
init(_ base: Base) {
self.base = base
}
mutating func next() -> ElementPair? {
if previousElement == nil { previousElement = base.next() }
let currentElement = base.next()
// Since `base.next()` returns `nil` when the end of the sequence
// is reached, we need to check `previousElement` and `currentElement `
// aren't `nil`. If either of them are, `nil` will be returned to signal
// there aren't any pairs left.
if let prev = previousElement, curr = currentElement {
previousElement = currentElement
return (prev, curr)
}
return nil
}
}
然后将PairGenerator
存入一个PairSequence
,符合SequenceType
;这意味着您可以在 for
循环中对其进行迭代。
struct PairSequence<Base: SequenceType> : SequenceType {
let generator: PairGenerator<Base.Generator>
init(_ base: Base) {
generator = PairGenerator(base.generate())
}
func generate() -> PairGenerator<Base.Generator> {
return generator
}
}
现在您需要一个函数,它将从符合 SequenceType
:
PairSequence
func pairs<Seq: SequenceType>(base: Seq) -> PairSequence<Seq> {
return PairSequence(base)
}
最后,你可以这样使用:
let myDict = ["1": 1, "2": 2, "3": 3, "4": 4]
let values = Array(myDict.values).sorted(<)
for (prev, curr) in pairs(values) {
println("\(prev), \(curr)")
}
// Prints:
// 1, 2
// 2, 3
// 3, 4
您可以使用 pairs(myDict)
,但就像@Martin R 和@matt 所说的那样 - 词典没有顺序,因此您可能无法按照预期的顺序获得结果。
有关 SequenceType
和 GeneratorType
的更多信息,我建议查看 Playing With Swift and Generators In Swift。
或者,正如@Martin R 在他的评论中指出的那样,您可以使用:
for (prev, curr) in zip(values, dropFirst(values)) {
println("\(prev), \(curr)")
}