Iterating Through a Dictionary in Swift

I am a little confused on the answer that Xcode is giving me to this experiment in the Swift Programming Language Guide:

// Use a for-in to iterate through a dictionary (experiment)

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25]
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
largest

I understand that as the dictionary is being transversed, the largest number is being set to the variable, largest. However, I am confused as to why Xcode is saying that largest is being set 5 times, or 1 time, or 3 times, depending on each test.

When looking through the code, I see that it should be set 6 times in "Prime" alone (2, 3, 5, 7, 11, 13). Then it should skip over any numbers in "Fibonacci" since those are all less than the largest, which is currently set to 13 from "Prime". Then, it should be set to 16, and finally 25 in "Square", yielding a total of 8 times.

Am I missing something entirely obvious?


Solution 1:

Dictionaries in Swift (and other languages) are not ordered. When you iterate through the dictionary, there's no guarantee that the order will match the initialization order. In this example, Swift processes the "Square" key before the others. You can see this by adding a print statement to the loop. 25 is the 5th element of Square so largest would be set 5 times for the 5 elements in Square and then would stay at 25.

let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25]
]
var largest = 0
for (kind, numbers) in interestingNumbers {
    println("kind: \(kind)")
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
largest

This prints:

kind: Square
kind: Prime
kind: Fibonacci

Solution 2:

let dict : [String : Any] = ["FirstName" : "Maninder" , "LastName" : "Singh" , "Address" : "Chandigarh"]
dict.forEach { print($0) }

Result would be

("FirstName", "Maninder") ("LastName", "Singh") ("Address", "Chandigarh")

Solution 3:

This is a user-defined function to iterate through a dictionary:

func findDic(dict: [String: String]) {
    for (key, value) in dict {
        print("\(key) : \(value)")
    }
}

findDic(dict: ["Animal": "Lion", "Bird": "Sparrow"])
// prints…
// Animal : Lion 
// Bird : Sparrow

Solution 4:

Here is an alternative for that experiment (Swift 3.0). This tells you exactly which kind of number was the largest.

let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]

var largest = 0
var whichKind: String? = nil

for (kind, numbers) in interestingNumbers {
    for number in numbers {
    if number > largest {
        whichKind = kind
        largest = number
    }
  }
}

print(whichKind)
print(largest)

OUTPUT:
Optional("Square")
25

Solution 5:

If you want to iterate over all the values:

dict.values.forEach { value in
    // print(value)
}