Skip to content

[Swift 6]: Update dictonary and its exercise #832

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 64 additions & 26 deletions concepts/dictionaries/about.md
Original file line number Diff line number Diff line change
@@ -1,41 +1,65 @@
# About

As [dictionaries][dictionaries] are one of Swift's three primary collection types, knowing how to work with dictionaries is a big part of knowing how to program in Swift.
[Dictionaries][dictionaries] are one of Swift's three primary collection types.
Dictionaries store mappings between _keys_ which are elements of one type and _values_ which are elements of another type (possibly the same type as that of the keys).

## Key Takeaways from this Exercise

- Dictionaries store mappings between _keys_ which are elements of one type and _values_
- Values can be of any type.
- Keys can be of any type that conforms to the [Hashable protocol][hashable-protocol-docs]. All of the basic Swift types have this property, and it can be added to other types.
- Dictionaries are unordered collections.
- Dictionaries can be defined using dictionary literals:
Dictionary literals are written as a series of `key: value` pairs, separated by commas, enclosed in square brackets.
Empty dictionaries can be written by following the type name of the dictionary by a pair of parenthesis, e.g. `[Int: String]()`, or, if the type can be determined from the context, as just a pair of square brackets surrounding a colon, `[:]`.
Type names for dictionaries are written in one of two ways: `Dictionary<K, V>` or `[K: V]` where `K` is the type of the keys in the dictionary and `V` is the type of the values.
When creating an empty dictionary, the type must be specified.

```swift
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]
let constants = ["pi": 3.14159, "e": 2.71828, "phi": 1.618033, "avogadro": 6.02214076e23]
var emptyDict1: [Int: Int] = [:]
var emptyDict2 = [Character: String]()
var emptyDict3 = Dictionary<Int, Double>()
```

- Empty dictionaries can be written by following the type name of the dictionary by a pair of parenthesis, e.g. `[Int: String]()`, or, if the type can be determined from the context, as just a pair of square brackets surrounding a colon, `[:]`.
- Type names for dictionaries are written in one of two ways: `Dictionary<K, V>` or `[K: V]` where `K` is the type of the keys in the dictionary and `V` is the type of the values.
- Dictionary elements can be accessed using subscript notation, e.g. `addresses["The Simpsons"]`.
- Values returned from these look-ups are optionals; `nil` is returned if a requested key is not present in the dictionary.
- To avoid the optional type of the return, one can supply a default value to return if the key in not found in the dictionary.
Elements of a dictionary can be accessed using subscript notation, where the name of the dictionary is followed by square brackets which enclose the key for which we want the corresponding value.

Note, however, that the value returned is not of type _Value_, but rather of optional type, _Value?_.
This is because one can supply a key that is not present in the dictionary.
In these cases, Swift chooses to return `nil` rather than throw an error.

```swift
let munster: String? = addresses["The Munsters"]
// Returns "1313 Mockingbird Lane"
let carmichael = sequences["Carmichael"]
// Returns [561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841]
let planck = constants["planck"]
// Returns nil
```

To avoid the optional type of the return, one can supply a default value to return if the key is not found in the dictionary.

```swift
let e: Double = constants["e", default: 0]
// => 2.71828
// Returns 2.71828
let hoagie: [Int] = sequences["Hoagie", default: []]
// => []
// Returns []
let betty = addresses["Betty Cooper", default: "Address unknown"]
// => "Address unknown"
// Returns "Address unknown"
```

- The subscript notation can be used to set the value associated with the supplied key, provided the dictionary was defined as a variable (i.e. using `var`).
- This can be used to update the value associated with a key or to add a new _key: value_ pair to the dictionary.
- Dictionaries can be sorted by passing a sorting function into the dictionary's `sorted(by:)` method.
- For-in loops can be used to iterate through the _key: value_ pairs of a dictionary
- Each pair is presented as a tuple and can be destructured like other tuples to assign each element to a name. For example, to print out the address book, one can write:
This subscript notation can be used to retrieve the value associated with that key as well as to set the value associated with that key, provided the dictionary was defined as a variable (i.e. using `var`).
This can be used to update the value associated with a key or to add a new _key: value_ pair to the dictionary.

```swift
sequence["Euler's totient"]?.append(contentsOf: [6,4])
sequence["Euler's totient"]
// Returns [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"
```

Like arrays, the _key: value_ pairs of a dictionary can be stepped through one at a time using a for-in loop.
This type of loop takes each _key: value_ pair of the dictionary and binds the pair to a specified name for further processing inside the loop body.
The pair is represented as a tuple and can be decomposed like other tuples to assign each element to a name. For example, to print out the address book, one can write:

```swift
for (name, address) in addresses {
Expand All @@ -49,8 +73,22 @@ for (name, address) in addresses {
// Buffy Summers lives at 1630 Revello Drive
```

[The other methods][dictionary-docs] available for working with dictionaries can be seen in the Apple Swift API documentation.
Like the other collection types, dictionaries can be sorted according to arbitrary sorting functions.
To do so, one must first define a function that takes two _key: value_ pairs, represented as tuples and returns a `Bool` such that the return value is `true` if the first _key: value_ pair should appear in the sorted result _before_ the second _key: value_ pair.

This function can then be passed into the dictionary's `sorted(by:)` method which will return a sorted array of _key: value_ pairs.
E.g. to sort the `constants` dictionary by the value of the constant plus the number of characters in the constant's name we could write:

```swift
func weirdSort(_ lhs: (String, Double), _ rhs: (String, Double)) -> Bool {
let left = lhs.1 + Double(lhs.0.count)
let right = rhs.1 + Double(rhs.0.count)
return left < right
}

let sortedConstants = constants.sorted(by: weirdSort)
// returns [(key "e", value 2.71828), (key "phi", value 1.618033), (key "pi", value 3.14159), (key "avogadro", value 6.02214076e+22)]
```


[dictionaries]: https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html#ID113
[dictionary-docs]: https://developer.apple.com/documentation/swift/Dictionary
[hashable-protocol-docs]: https://developer.apple.com/documentation/swift/hashable
[dictionaries]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/#Dictionaries
47 changes: 30 additions & 17 deletions concepts/dictionaries/introduction.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# Introduction

Dictionaries are one of Swift's three primary collection types. Dictionaries store mappings between _keys_ which are elements of one type and _values_ which are elements of another type (possibly the same type as that of the keys).
[Dictionaries][dictionaries] are one of Swift's three primary collection types.
Dictionaries store mappings between _keys_ which are elements of one type and _values_ which are elements of another type (possibly the same type as that of the keys).

Dictionary literals are written as a series of `key: value` pairs, separated by commas, enclosed in square brackets. Empty dictionaries can be written by following the type name of the dictionary by a pair of parenthesis, e.g. `[Int: String]()`, or, if the type can be determined from the context, as just a pair of square brackets surrounding a colon, `[:]`. Type names for dictionaries are written in one of two ways: `Dictionary<K, V>` or `[K: V]` where `K` is the type of the keys in the dictionary and `V` is the type of the values. When creating an empty array, the type must be specified.
Dictionary literals are written as a series of `key: value` pairs, separated by commas, enclosed in square brackets.
Empty dictionaries can be written by following the type name of the dictionary by a pair of parenthesis, e.g. `[Int: String]()`, or, if the type can be determined from the context, as just a pair of square brackets surrounding a colon, `[:]`.
Type names for dictionaries are written in one of two ways: `Dictionary<K, V>` or `[K: V]` where `K` is the type of the keys in the dictionary and `V` is the type of the values.
When creating an empty dictionary, the type must be specified.

```swift
var addresses: Dictionary<String, String> = ["The Munsters": "1313 Mockingbird Lane", "The Simpsons": "742 Evergreen Terrace", "Buffy Summers": "1630 Revello Drive"]
Expand All @@ -15,42 +19,47 @@ var emptyDict3 = Dictionary<Int, Double>()

Elements of a dictionary can be accessed using subscript notation, where the name of the dictionary is followed by square brackets which enclose the key for which we want the corresponding value.

Note, however, that the value returned is not of type _Value_, but rather of optional type, _Value?_. This is because one can supply a key that is not present in the dictionary. In these cases, Swift chooses to return `nil` rather than throw an error.
Note, however, that the value returned is not of type _Value_, but rather of optional type, _Value?_.
This is because one can supply a key that is not present in the dictionary.
In these cases, Swift chooses to return `nil` rather than throw an error.

```swift
let munster: String? = addresses["The Munsters"]
// => "1313 Mockingbird Lane"
// Returns "1313 Mockingbird Lane"
let carmichael = sequences["Carmichael"]
// => [561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841]
// Returns [561, 1105, 1729, 2465, 2821, 6601, 8911, 10585, 15841]
let planck = constants["planck"]
// => nil
// Returns nil
```

To avoid the optional type of the return, one can supply a default value to return if the key if not found in the dictionary.
To avoid the optional type of the return, one can supply a default value to return if the key is not found in the dictionary.

```swift
let e: Double = constants["e", default: 0]
// => 2.71828
// Returns 2.71828
let hoagie: [Int] = sequences["Hoagie", default: []]
// => []
// Returns []
let betty = addresses["Betty Cooper", default: "Address unknown"]
// => "Address unknown"
// Returns "Address unknown"
```

This subscript notation can be used to retrieve the value associated with that key as well as to set the value associated with that key, provided the dictionary was defined as a variable (i.e. using `var`). This can be used to update the value associated with a key or to add a new _key: value_ pair to the dictionary.
This subscript notation can be used to retrieve the value associated with that key as well as to set the value associated with that key, provided the dictionary was defined as a variable (i.e. using `var`).
This can be used to update the value associated with a key or to add a new _key: value_ pair to the dictionary.

```swift
sequence["Euler's totient"]?.append(contentsOf: [6,4])
sequence["Euler's totient"]
// => [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
// Returns [1, 1, 2, 2, 4, 2, 6, 4, 6, 4]
addresses["Betty Cooper"] = "111 Queens Ave."
addresses["Betty Cooper", default: "Address unknown"]
// => "111 Queens Ave."
// Returns "111 Queens Ave."
constants["Gelfond's"] = 23.140692
// compiler error: "Cannot assign through subscript: 'constants' is a 'let' constant"
```

Like arrays, the _key: value_ pairs of a dictionary can be stepped through one at a time using a for-in loop. This type of loop takes each _key: value_ pair of the dictionary and binds the pair to a specified name for further processing inside the loop body. The pair is represented as a tuple and can be decomposed like other tuples to assign each element to a name. For example, to print out the address book, one can write:
Like arrays, the _key: value_ pairs of a dictionary can be stepped through one at a time using a for-in loop.
This type of loop takes each _key: value_ pair of the dictionary and binds the pair to a specified name for further processing inside the loop body.
The pair is represented as a tuple and can be decomposed like other tuples to assign each element to a name. For example, to print out the address book, one can write:

```swift
for (name, address) in addresses {
Expand All @@ -64,9 +73,11 @@ for (name, address) in addresses {
// Buffy Summers lives at 1630 Revello Drive
```

Like the other collection types, dictionaries can be sorted according to arbitrary sorting functions. To do so, one must first define a function that takes two _key: value_ pairs, represented as tuples and returns a `Bool` such that the return value is `true` if the first _key: value_ pair should appear in the sorted result _before_ the second _key: value_ pair.
Like the other collection types, dictionaries can be sorted according to arbitrary sorting functions.
To do so, one must first define a function that takes two _key: value_ pairs, represented as tuples and returns a `Bool` such that the return value is `true` if the first _key: value_ pair should appear in the sorted result _before_ the second _key: value_ pair.

This function can then be passed into the dictionary's `sorted(by:)` method which will return a sorted array of _key: value_ pairs. E.g. to sort the `constants` dictionary by the value of the constant plus the number of characters in the constant's name we could write:
This function can then be passed into the dictionary's `sorted(by:)` method which will return a sorted array of _key: value_ pairs.
E.g. to sort the `constants` dictionary by the value of the constant plus the number of characters in the constant's name we could write:

```swift
func weirdSort(_ lhs: (String, Double), _ rhs: (String, Double)) -> Bool {
Expand All @@ -76,5 +87,7 @@ func weirdSort(_ lhs: (String, Double), _ rhs: (String, Double)) -> Bool {
}

let sortedConstants = constants.sorted(by: weirdSort)
// => [(key "e", value 2.71828), (key "phi", value 1.618033), (key "pi", value 3.14159), (key "avogadro", value 6.02214076e+22)]
// returns [(key "e", value 2.71828), (key "phi", value 1.618033), (key "pi", value 3.14159), (key "avogadro", value 6.02214076e+22)]
```

[dictionaries]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/#Dictionaries
11 changes: 10 additions & 1 deletion concepts/dictionaries/links.json
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
[]
[
{
"url": "https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/#Dictionaries",
"description": "Swift Book: Dictionaries"
},
{
"url": "https://developer.apple.com/documentation/swift/dictionary",
"description": "Swift docs: Dictionary"
}
]
7 changes: 4 additions & 3 deletions exercises/concept/high-score-board/.docs/hints.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## 1. Define a new high score dictionary

- Empty dictionaries can be initialized by following the type name with a pair of empty parentheses or, if the type can be determined from context, by using the empty dictionary literal.
- [Empty dictionaries][empty-dictionary] can be initialized by following the type name with a pair of empty parentheses or, if the type can be determined from context, by using the empty dictionary literal.

## 2. Add players to the high score dictionary

Expand Down Expand Up @@ -36,6 +36,7 @@
- You will need to define a sorting function of type `((String, Int), (String, Int)) -> Bool` to pass in to the `sorted(by:)` method.
- The sorting function should return `true` if the left-hand key/value pair should appear _before_ the right-hand key/value pair in the sorted output.

[dictionaries]: https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html#ID113
[dictionaries]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/#Dictionaries
[empty-dictionary]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/#Creating-an-Empty-Dictionary
[dictionary-docs]: https://developer.apple.com/documentation/swift/Dictionary
[dictionary-subscripts]: https://docs.swift.org/swift-book/LanguageGuide/CollectionTypes.html#ID116
[dictionary-subscripts]: https://docs.swift.org/swift-book/documentation/the-swift-programming-language/collectiontypes/#Accessing-and-Modifying-a-Dictionary
Loading