问题
I have this code
for (k, v) in myDict {
println(k)
}
How do I access the next key in the dictionary (e.g. myDict[k + 1])?
Thanks in advance!
回答1:
There is no such thing as "the next key"; dictionaries have no order.
Since, however, you are iterating through the dictionary...
for (k, v) in myDict {
println(k)
}
I'm going to assume that what you mean is: how can I know, on this iteration, what k would be on the next iteration?
A simple solution would be to coerce the dictionary to an array (of key-value tuples):
let arr = Array(myDict)
Now you have something with integer indexes. So you can enumerate it like this:
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)")
}
}
The truth is, of course, that you can enumerate a dictionary directly, but indexes are not integers, so they are a little harder to work with. Martin R is also showing an approach illustrating that point.
回答2:
I don't know if this is what you are looking for, but you can
iterate through a dictionary in a "similar" way as iterating
through an array by using the DictionaryIndex<Key, Value> as an index:
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)")
}
}
Sample output:
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
回答3:
A possible solution is to create Generator which returns the current and previous values in a sequence. For this you need a custom Generator which will return a tuple, containing the previous and current values from a sequence, from 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
}
}
The PairGenerator is then stored in a PairSequence, which conforms to SequenceType; this means you can iterate over it in a for loop.
struct PairSequence<Base: SequenceType> : SequenceType {
let generator: PairGenerator<Base.Generator>
init(_ base: Base) {
generator = PairGenerator(base.generate())
}
func generate() -> PairGenerator<Base.Generator> {
return generator
}
}
Now you need a function which will create a PairSequence from an object that conforms to SequenceType:
func pairs<Seq: SequenceType>(base: Seq) -> PairSequence<Seq> {
return PairSequence(base)
}
Finally, you can use this like so:
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
You could use pairs(myDict), but like @Martin R and @matt said - Dictionaries don't have an order so you may not get the results in the order you expected.
For more information on SequenceType and GeneratorType, I'd recommend looking at Playing With Swift and Generators In Swift.
Or, as @Martin R pointed out in his comment, you could use:
for (prev, curr) in zip(values, dropFirst(values)) {
println("\(prev), \(curr)")
}
来源:https://stackoverflow.com/questions/30464861/how-to-access-the-next-key-in-a-swift-dictionary