Skip to content

Commit 9ca8c27

Browse files
colinleachColin LeachColin Leach
authored
WIP draft of pairs-and-dicts concept (#812)
* WIP draft of `pairs-and-dicts` concept * expanded info on modifying and searching * Update about.md * Update links.json Oops, I forgot to add some description text. * concepts.wip exercises changed to deprecated * Revert "concepts.wip exercises changed to deprecated" This reverts commit 28f91a8. * Change annelyns-infiltration slug for old version * Revert "Change annelyns-infiltration slug for old version" This reverts commit 09dfe5d. * moved from wip, config.json added * Update about.md * Update about.md * Update introduction.md --------- Co-authored-by: Colin Leach <[email protected]> Co-authored-by: Colin Leach <[email protected]>
1 parent 7f7d5b0 commit 9ca8c27

File tree

5 files changed

+318
-0
lines changed

5 files changed

+318
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"authors": [
3+
"colinleach"
4+
],
5+
"contributors": [],
6+
"blurb": "A Dict is a collection of key => value Pairs, though the same Pair type has many other uses."
7+
}

concepts/pairs-and-dicts/about.md

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# About
2+
3+
## Pairs
4+
5+
A [`Pair`][pair] is just two items joined together.
6+
The items are then imaginatively called `first` and `second`.
7+
8+
Create them either with the `=>` operator or the `Pair()` constructor.
9+
10+
```julia-repl
11+
julia> p1 = "k" => 2
12+
"k" => 2
13+
14+
julia> p2 = Pair("k", 2)
15+
"k" => 2
16+
17+
# Both forms of syntax give the same result
18+
julia> p1 == p2
19+
true
20+
21+
# Each component has its own separate type
22+
julia> dump(p1)
23+
Pair{String, Int64}
24+
first: String "k"
25+
second: Int64 2
26+
27+
# Get a component using dot syntax
28+
julia> p1.first
29+
"k"
30+
31+
julia> p1.second
32+
2
33+
```
34+
35+
## Dicts
36+
37+
A `Vector` of Pairs is like any other array: ordered, homogeneous in type, and stored consecutively in memory.
38+
39+
```julia-repl
40+
julia> pv = ['a' => 1, 'b' => 2, 'c' => 3]
41+
3-element Vector{Pair{Char, Int64}}:
42+
'a' => 1
43+
'b' => 2
44+
'c' => 3
45+
46+
# Each pair is a single entry
47+
julia> length(pv)
48+
3
49+
```
50+
51+
A [`Dict`][dict] is superficially similar, but storage is now implemented in a way that allows fast retrieval by key, known as a "hash table", even when the number of entries grows large.
52+
53+
```julia-repl
54+
julia> pd = Dict('a' => 1, 'b' => 2, 'c' => 3) # or Dict(pv) gives same result
55+
Dict{Char, Int64} with 3 entries:
56+
'a' => 1
57+
'c' => 3
58+
'b' => 2
59+
60+
julia> pd['b']
61+
2
62+
63+
# Key must exist
64+
julia> pd['d']
65+
ERROR: KeyError: key 'd' not found
66+
67+
# Generators are accepted in the constructor (and note the unordered output)
68+
julia> Dict(x => x^2 for x in 1:5)
69+
julia> Dict(x => 1 / x for x in 1:5)
70+
Dict{Int64, Float64} with 5 entries:
71+
5 => 0.2
72+
4 => 0.25
73+
2 => 0.5
74+
3 => 0.333333
75+
1 => 1.0
76+
```
77+
78+
In other languages, something very similar to a `Dict` might be called a dictionary (Python), a Hash (Ruby) or a HashMap (Java).
79+
80+
For Pairs, whether in isolation or in a Vector, there are few constraints on the type of each component.
81+
82+
To be valid in a `Dict`, the `Pair` must be a `key => value` pair, where the `key` is "hashable".
83+
Most importantly, this means the `key` must be _immutable_, so `Char`, `Int`, `String`, `Symbol`, and `Tuple` are all fine, but `Vector` is not allowed.
84+
85+
If mutable keys are important to you, there is a separate but much less common [`IdDict`][iddict] type that can allow this.
86+
See the [manual][dict] for several other variants on the `Dict` type.
87+
88+
### Modifying a Dict
89+
90+
Entries can be added, with a new key, or overwritten, with an existing key.
91+
92+
```julia-repl
93+
julia> pd
94+
Dict{Char, Int64} with 3 entries:
95+
'a' => 1
96+
'c' => 3
97+
'b' => 2
98+
99+
# Add
100+
julia> pd['d'] = 4
101+
4
102+
103+
# Overwrite
104+
julia> pd['a'] = 42
105+
42
106+
107+
julia> pd
108+
Dict{Char, Int64} with 4 entries:
109+
'a' => 42
110+
'c' => 3
111+
'd' => 4
112+
'b' => 2
113+
```
114+
115+
To remove an entry, use the `delete!()` function, which will change the Dict if the key exists and silently do nothing otherwise.
116+
117+
```julia-repl
118+
julia> delete!(pd, 'd')
119+
Dict{Char, Int64} with 3 entries:
120+
'a' => 42
121+
'c' => 3
122+
'b' => 2
123+
```
124+
125+
### Checking if a key or value exists
126+
127+
There are different approaches.
128+
To check a key, there is a `haskey()` function:
129+
130+
```julia-repl
131+
julia> haskey(pd, 'b')
132+
true
133+
```
134+
135+
Alternatively, search either the keys or the values:
136+
137+
```julia-repl
138+
julia> 'b' in keys(pd)
139+
true
140+
141+
julia> 43 in values(pd)
142+
false
143+
144+
julia> 42 ∈ values(pd)
145+
true
146+
```
147+
148+
This remains efficient at scale, as the `keys()` and `values()` functions each return an iterator with a fast search algorithm.
149+
150+
151+
[pair]: https://docs.julialang.org/en/v1/base/collections/#Core.Pair
152+
[dict]: https://docs.julialang.org/en/v1/base/collections/#Dictionaries
153+
[iddict]: https://docs.julialang.org/en/v1/base/collections/#Base.IdDict
+143
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
# Introduction
2+
3+
## Pairs
4+
5+
A `Pair` is just two items joined together.
6+
The items are then imaginatively called `first` and `second`.
7+
8+
Create them either with the `=>` operator or the `Pair()` constructor.
9+
10+
```julia-repl
11+
julia> p1 = "k" => 2
12+
"k" => 2
13+
14+
julia> p2 = Pair("k", 2)
15+
"k" => 2
16+
17+
# Both forms of syntax give the same result
18+
julia> p1 == p2
19+
true
20+
21+
# Each component has its own separate type
22+
julia> dump(p1)
23+
Pair{String, Int64}
24+
first: String "k"
25+
second: Int64 2
26+
27+
# Get a component using dot syntax
28+
julia> p1.first
29+
"k"
30+
31+
julia> p1.second
32+
2
33+
```
34+
35+
## Dicts
36+
37+
A `Vector` of Pairs is like any other array: ordered, homogeneous in type, and stored consecutively in memory.
38+
39+
```julia-repl
40+
julia> pv = ['a' => 1, 'b' => 2, 'c' => 3]
41+
3-element Vector{Pair{Char, Int64}}:
42+
'a' => 1
43+
'b' => 2
44+
'c' => 3
45+
46+
# Each pair is a single entry
47+
julia> length(pv)
48+
3
49+
```
50+
51+
A `Dict` is superficially similar, but storage is now implemented in a way that allows fast retrieval by key, even when the number of entries grows large.
52+
53+
```julia-repl
54+
julia> pd = Dict('a' => 1, 'b' => 2, 'c' => 3)
55+
Dict{Char, Int64} with 3 entries:
56+
'a' => 1
57+
'c' => 3
58+
'b' => 2
59+
60+
julia> pd['b']
61+
2
62+
63+
# Key must exist
64+
julia> pd['d']
65+
ERROR: KeyError: key 'd' not found
66+
67+
# Generators are accepted in the constructor (and note the unordered output)
68+
julia> Dict(x => x^2 for x in 1:5)
69+
julia> Dict(x => 1 / x for x in 1:5)
70+
Dict{Int64, Float64} with 5 entries:
71+
5 => 0.2
72+
4 => 0.25
73+
2 => 0.5
74+
3 => 0.333333
75+
1 => 1.0
76+
```
77+
78+
In other languages, something very similar to a `Dict` might be called a dictionary (Python), a Hash (Ruby) or a HashMap (Java).
79+
80+
For Pairs, whether in isolation or in a Vector, there are few constraints on the type of each component.
81+
82+
To be valid in a `Dict`, the `Pair` must be a `key => value` pair, where the `key` is "hashable".
83+
Most importantly, this means the `key` must be _immutable_, so `Char`, `Int`, `String`, `Symbol`, and `Tuple` are all fine, but `Vector` is not allowed.
84+
85+
### Modifying a Dict
86+
87+
Entries can be added, with a new key, or overwritten, with an existing key.
88+
89+
```julia-repl
90+
julia> pd
91+
Dict{Char, Int64} with 3 entries:
92+
'a' => 1
93+
'c' => 3
94+
'b' => 2
95+
96+
# Add
97+
julia> pd['d'] = 4
98+
4
99+
100+
# Overwrite
101+
julia> pd['a'] = 42
102+
42
103+
104+
julia> pd
105+
Dict{Char, Int64} with 4 entries:
106+
'a' => 42
107+
'c' => 3
108+
'd' => 4
109+
'b' => 2
110+
```
111+
112+
To remove an entry, use the `delete!()` function, which will change the Dict if the key exists and silently do nothing otherwise.
113+
114+
```julia-repl
115+
julia> delete!(pd, 'd')
116+
Dict{Char, Int64} with 3 entries:
117+
'a' => 42
118+
'c' => 3
119+
'b' => 2
120+
```
121+
122+
### Checking if a key or value exists
123+
124+
There are different approaches.
125+
To check a key, there is a `haskey()` function:
126+
127+
```julia-repl
128+
julia> haskey(pd, 'b')
129+
true
130+
```
131+
132+
Alternatively, search either the keys or the values:
133+
134+
```julia-repl
135+
julia> 'b' in keys(pd)
136+
true
137+
138+
julia> 43 in values(pd)
139+
false
140+
141+
julia> 42 ∈ values(pd)
142+
true
143+
```

concepts/pairs-and-dicts/links.json

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[
2+
{
3+
"url": "https://docs.julialang.org/en/v1/base/collections/#Core.Pair",
4+
"description": "Pair section in the manual."
5+
},
6+
{
7+
"url": "https://docs.julialang.org/en/v1/base/collections/#Dictionaries",
8+
"description": "Introduction to dictionaries in the manual."
9+
}
10+
]

config.json

+5
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,11 @@
12671267
"uuid": "95b8b60b-fd78-4ec1-9d1c-ac3f11107727",
12681268
"slug": "chars",
12691269
"name": "Chars"
1270+
},
1271+
{
1272+
"uuid": "0d312606-7738-4b0a-9c33-564c40c6f35d",
1273+
"slug": "pairs-and-dicts",
1274+
"name": "Pairs And Dicts"
12701275
}
12711276
],
12721277
"key_features": [

0 commit comments

Comments
 (0)