Chapter 3 · Data
Dictionaries and sets
Step 1 of 20 · Concept
A dictionary finds a value by its key
In this lesson you look values up by a key and count things. You also keep each item once, in a set.
ages = {"Ada": 36, "Alan": 41}
print(ages["Ada"])
- A dictionary pairs each key with a value:
"Ada"with36. ages["Ada"]finds the value of the key"Ada", so it prints36.
Step 2 of 20 · Concept
What a dictionary can do
| write | what it does |
|---|---|
ages["Grace"] = 85 | adds the key "Grace", or changes its value if it is there |
del ages["Alan"] | removes the key "Alan" and its value |
"Ada" in ages | True when "Ada" is a key |
ages.get("Bo", 0) | the value of "Bo", or 0 when there is no such key |
len(ages) | how many keys there are |
{} is an empty dictionary. A dictionary prints as its pairs: {'Ada': 36}.
Step 3 of 20 · Quiz
Predict the lookups
Type exactly what this program prints.
ages = {"Ada": 36, "Alan": 41}
ages["Ada"] = 37
ages["Grace"] = 85
print(ages["Ada"], len(ages))
print(ages.get("Bo", 0))
print("Alan" in ages, 41 in ages)
print(ages)
Step 4 of 20 · Demo
See it run
Run it and compare with your answer. The new key "Grace" went to the end.
Step 5 of 20 · Quiz
Why did it stop?
This program stops. Why?
ages = {"Ada": 36}
print(ages["Alan"])
Traceback (most recent call last):
File "main.py", line 2, in <module>
print(ages["Alan"])
~~~~^^^^^^^^
KeyError: 'Alan'
Step 6 of 20 · Exercise
Your turn: a phone book
Complete the phone book.
- Add Grace, with the number
555-0123. - Change Alan's number to
555-0100. - Print the numbers of Grace, Alan and Bo, with
unknownfor a name that is missing. - Print how many names there are.
The output must be exactly:
Grace: 555-0123
Alan: 555-0100
Bo: unknown
Names: 3
Adding and changing are the same line, phones[key] = value. Whether the key is there decides which one happens.
phones["Bo"] would stop with a KeyError. get with a second value gives that value for a missing key.
print("Bo:", phones.get("Bo", "unknown"))
Step 7 of 20 · Concept
Every pair, in the order you added them
for name in ages:
print(name)
for name, age in ages.items():
print(name, age)
for name in agesgoes through the keys.ages.items()gives each pair as a tuple.name, ageunpacks it (lesson 11).ages.keys()gives the keys alone,ages.values()the values alone.sorted(ages)gives the keys as a new list, in alphabetical order (capitals first: lesson 13).
A dictionary keeps its keys in the order you added them. Changing a value keeps the key in its place.
A value can be a list. Its key holds an arrow to that one list, so marks["Ada"].append(85) changes it.
Step 8 of 20 · Quiz
Predict the order
"Ada" is deleted, then added again. Type exactly what this program prints.
ages = {"Ada": 36, "Alan": 41, "Grace": 85}
del ages["Ada"]
ages["Ada"] = 37
ages["Alan"] = 42
for name, age in ages.items():
print(name, age)
print(sorted(ages))
print(sum(ages.values()))
marks = {"Ada": [90]}
marks["Ada"].append(85)
print(marks)
Step 9 of 20 · Demo
See it run
Run it and compare with your answer.
Step 10 of 20 · Concept
Counting with a dictionary
A dictionary can count. Each word is a key, and its value is how often it came.
counts = {}
for w in "the cat the".split():
counts[w] = counts.get(w, 0) + 1
print(counts)
- The first time a word comes,
getgives0, so its count becomes 1. - Each next time,
getgives the count so far, and the line adds 1.
Step 11 of 20 · Trace
Watch the counts grow
w and counts are names in the <module> frame. counts points at the dictionary on the heap. Its counts are
drawn in their cells, the shorthand of lesson 3.
Press Next to run one round at a time.
counts = {}
for w in "the cat the".split():
counts[w] = counts.get(w, 0) + 1
print(counts)- The loop starts:
wis"the", and the dictionary is empty. Line 3 is next. "the"was no key, sogetgave 0:"the"is now 1.wis"cat"."cat"is added with 1.wis"the"again.getgave 1, so"the"is now 2. The words are used up: line 4 is next.- Line 4 printed the dictionary, its keys in the order they came.
Step 12 of 20 · Exercise
Your turn: counting words
Count how often each word of text comes. Then print each word with its count, in the order the words first came.
The output must be exactly:
red: 3
blue: 2
green: 1
Two loops: one over the words to count them, then one over the pairs of counts to print them.
The counting line is counts[w] = counts.get(w, 0) + 1, with your loop's name for w. The second loop is
for word, n in counts.items():.
for word in text.split():
counts[word] = counts.get(word, 0) + 1
Step 13 of 20 · Demo
Keys must not change
A key must be a value that never changes: text, a number, or a tuple of such values. A list can change, so it cannot be a key.
Run it. The tuple key works. The list key stops the program: read the last line of the traceback.
Step 14 of 20 · Concept
A set keeps each item once
A set holds each item once, in no fixed order.
unique = set("the cat and the hat".split())
| write | gives |
|---|---|
{1, 2}, set() | a set of two numbers; an empty set ({} is a dictionary) |
s.add(x), x in s | puts x in, once; True when x is in |
set(words) | each item of words once |
a | b, a & b | the items in either set; the items in both |
Step 15 of 20 · Quiz
Predict the unique words
Type exactly what this program prints.
words = "the cat and the hat".split()
unique = set(words)
print(len(words), len(unique))
print(sorted(unique))
pets = set()
pets.add("dog")
pets.add("cat")
pets.add("dog")
print(len(pets), "cat" in pets)
print(sorted(unique & pets))
print(sorted(unique | pets))
Step 16 of 20 · Demo
See it run
Run it and compare with your answer. Then change the last line to print(unique | pets), and run it a few times:
the order changes.
Step 17 of 20 · Concept
A list, a dictionary or a set?
Each keeps a group of values. Choose by what you will ask of it.
| use | when | for example |
|---|---|---|
| a list | the order matters, and an item may come twice | the scores, as they came |
| a dictionary | you look a value up by its key | a phone book |
| a set | each item counts once, and order does not matter | the words a text uses |
| a dictionary as a record | each key names a part of one thing | {"owner": "Ada", "balance": 0} |
Step 18 of 20 · Check yourself
Check yourself: a gradebook
grades pairs each name with a list of scores.
- Add Cy, with the scores 88 and 92.
- Add the score 95 to Bo's list.
- Print each name in alphabetical order, with its average to one decimal.
The output must be exactly:
Ada: 85.0
Bo: 76.7
Cy: 90.0
Lin: 85.0
One loop over the names in alphabetical order. A name's average is the sum of its list over the list's length.
Step 19 of 20 · Challenge · optional
Challenge: anagrams
Optional. Two words are anagrams when they use the same letters: listen and silent.
Group the words that are anagrams of each other. Print each group of two or more words on one line, in the order the groups first came. The output must be exactly:
listen silent enlist
cat act
Anagrams have the same letters once you put them in order. Those letters, in order, can be a key.
sorted works on text too: sorted("cat") is ['a', 'c', 't'], and "".join of that is "act". Make each
key's value a list of words.
key = "".join(sorted(w))
Step 20 of 20 · Recap
Recap
ages["Ada"]finds a value by its key. A missing key is aKeyError;getgives a default.ages["Grace"] = 85adds or changes;delremoves;inasks about the keys.- A dictionary keeps its keys in the order you added them.
counts[w] = counts.get(w, 0) + 1counts. A key must not change: no lists.- A set holds each item once, in no order: print
sorted(s).
Next: lesson 13 builds a list in one line, and sorts by any key you choose.
Review
4 questions from this lesson, in a new order each time. Answer from memory: 3 of 4 right on the first try passes. On a day after you finish the lesson, a pass earns 15 XP.
The review needs JavaScript.
ages = {"Ada": 36, "Alan": 41}
ages["Ada"] = 37
ages["Grace"] = 85
print(ages["Ada"], len(ages))
print(ages.get("Bo", 0))
print("Alan" in ages, 41 in ages)
print(ages)
phones = {"Ada": "555-0101", "Alan": "555-0199"}
# 1. add Grace
# 2. change Alan's number
# 3. print Grace, Alan and Bo
# 4. print how many names
ages = {"Ada": 36, "Alan": 41, "Grace": 85}
del ages["Ada"]
ages["Ada"] = 37
ages["Alan"] = 42
for name, age in ages.items():
print(name, age)
print(sorted(ages))
print(sum(ages.values()))
marks = {"Ada": [90]}
marks["Ada"].append(85)
print(marks)
text = "red blue red green blue red"
counts = {}
# count each word of text in counts,
# then print each word with its count
where = {}
where[(2, 3)] = "treasure"
print(where[(2, 3)])
key = ["a", "b"]
where[key] = 1
words = "the cat and the hat".split()
unique = set(words)
print(len(words), len(unique))
print(sorted(unique))
pets = set()
pets.add("dog")
pets.add("cat")
pets.add("dog")
print(len(pets), "cat" in pets)
print(sorted(unique & pets))
print(sorted(unique | pets))
grades = {"Lin": [90, 80], "Ada": [70, 85, 100], "Bo": [60, 75]}
# 1. add Cy with the scores 88 and 92
# 2. add the score 95 to Bo's list
# 3. print each name, in order, with its average
words = ["listen", "silent", "cat", "act", "dog", "enlist"]
groups = {}
# put each word in its group of anagrams,
# then print each group of two or more words