Dictionaries are one of Swift's primary collection types. A dictionary stores unordered associations between unique keys and corresponding values. All keys in a dictionary must be of the same type, and all values must also share the same type.
Dictionary literals are written as comma-separated key: value pairs enclosed in square brackets:
var addresses: Dictionary<String, String> = [
"The Munsters": "1313 Mockingbird Lane",
"The Simpsons": "742 Evergreen Terrace",
"Buffy Summers": "1630 Revello Drive"
]
var sequences: [String: [Int]] = [
"Euler's totient": [1, 1, 2, 2, 4, 2, 6, 4],
"Lazy caterer": [1, 2, 4, 7, 11, 16, 22, 29, 37],
"Carmichael": [561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841]
]
let constants = [
"pi": 3.14159,
"e": 2.71828,
"phi": 1.618033,
"avogadro": 6.02214076e23
]
Dictionary types can be written explicitly in two ways: Dictionary<Key, Value> or the shorthand syntax [Key: Value].
To create an empty dictionary, specify its key and value types explicitly:
var emptyDict1: [Int: Int] = [:]
var emptyDict2 = [Character: String]()
var emptyDict3 = Dictionary<Int, Double>()
You can access values using subscript notation: place the key inside square brackets after the dictionary name.
Because a key might not exist in the dictionary, subscript access returns an optional (Value?).
If the key is present, Swift returns the wrapped value; if not, it returns nil:
let munster: String? = addresses["The Munsters"]
// Returns Optional("1313 Mockingbird Lane")
let carmichael = sequences["Carmichael"]
// Returns Optional([561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841])
let planck = constants["planck"]
// Returns nil
To avoid working with optionals, you can provide a default value using the default parameter:
let e: Double = constants["e", default: 0]
// Returns 2.71828
let hoagie: [Int] = sequences["Hoagie", default: []]
// Returns []
let betty = addresses["Betty Cooper", default: "Address unknown"]
// Returns "Address unknown"
For mutable dictionaries declared with var, you can add or update key-value pairs using subscript assignment:
sequences["Euler's totient"]?.append(contentsOf: [6, 4])
// sequences["Euler's totient"] is now [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
addresses["Betty Cooper"] = "111 Queens Ave."
addresses["Betty Cooper", default: "Address unknown"]
// Returns "111 Queens Ave."
constants["Gelfond's"] = 23.140692
// Compiler error: Cannot assign through subscript: 'constants' is a 'let' constant
You can iterate through each key-value pair of a dictionary using a for-in loop.
Each item is provided as a (key, value) tuple:
for (name, address) in addresses {
print("\(name) lives at \(address)")
}
Because dictionaries are unordered, sorting them produces an array of key-value pairs.
You can pass a closure to the sorted(by:) method that compares two (key, value) tuples and returns true if the first tuple should appear before the second:
func sortByNameLengthThenValue(_ lhs: (key: String, value: Double), _ rhs: (key: String, value: Double)) -> Bool {
let left = lhs.value + Double(lhs.key.count)
let right = rhs.value + Double(rhs.key.count)
return left < right
}
let sortedConstants = constants.sorted(by: sortByNameLengthThenValue)
In this exercise, you're implementing a way to keep track of the high scores for the most popular game in your local arcade hall.
You have 7 functions to implement, all related to returning and manipulating a dictionary of high score data.
Create a function newScoreBoard() that takes no parameters and returns a new high score dictionary which uses values of type String for the keys and values of type Int as the values.
To add a player to the high score dictionary, define addPlayer(_:_:_:), which is a function which takes 3 parameters:
var highScores = newScoreBoard()
addPlayer(&highScores, "Dave Thomas")
// Returns ["Dave Thomas": 0]
addPlayer(&highScores, "José Valim", 486_373)
// Returns ["Dave Thomas": 0, "José Valim": 486_373]
To remove a player from the high score dictionary, define removePlayer(_:_:), which takes 2 parameters:
This function should remove the player from the dictionary if they are in it and do nothing otherwise.
var highScores = ["Dave Thomas": 0, "José Valim": 486_373]
removePlayer(&highScores, "Dave Thomas")
// Returns ["José Valim": 486_373]
removePlayer(&highScores, "Rose Fanaras")
// Returns ["José Valim": 486_373]
To reset a player's score, define resetPlayer(_:_:), which takes 2 parameters:
The function will set the score of the player to 0. If the player is not in the dictionary, then nothing should happen.
var highScores = ["Dave Thomas": 486_373, "José Valim": 10]
resetScore(&highScores, "Dave Thomas")
// Returns ["Dave Thomas": 0, "José Valim": 10]
To update a players score by adding to the previous score, define updateScore, which takes 3 parameters:
var highScores = ["Dave Thomas": 0, "José Valim": 486_373]
addPlayer(&highScores, "Freyja Ćirić", 12_771_008)
updateScore(&highScores, "Freyja Ćirić", 73)
// Returns ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_081]
Define the function orderByPlayers, which takes 1 parameter:
The function will return an array of (String, Int) tuples that are the players and their high scores sorted in ascending order by the player's name.
var highScores = ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_091]
orderByPlayers(highScores)
// Returns [("Dave Thomas", 0), ("Freyja Ćirić", 12_771_091), ("José Valim", 486_373)]
To get a list of players ordered by scores in decreasing order, define orderByScores, which takes 1 parameter:
The function will return an array of (String, Int) tuples that are the players and their high scores sorted in descending order by the player's score.
var highScores = ["Dave Thomas": 0, "José Valim": 486_373, "Freyja Ćirić": 12_771_091]
orderByScores(highScores)
// Returns [("Freyja Ćirić", 12_771_091), ("José Valim", 486_373), ("Dave Thomas", 0)]
Sign up to Exercism to learn and master Swift with 35 concepts116 exercises, and real human mentoring, all for free.