Word Counting and Choosing a Container
Seven problems. The first five exercise one container each, the sixth is a full word-frequency task, and the last involves no code at all — pick a container for each scenario and justify it.
Contents
What this session is for
- Get comfortable using dictionaries for counting and lookup tables
- Use sets for deduplication and membership tests
- Handle text with
split,joinandstrip - Build the instinct of choosing a container before writing anything
Problems
6-1 Invert a dictionary
Implement invert(d: dict[str, int]) -> dict[int, str], swapping keys and values.
invert({"a": 1, "b": 2}) → {1: "a", 2: "b"}
In your submission notes, answer: what happens if two keys map to the same value? Give a concrete example.
6-2 Deduplicate, keeping order
Implement unique_ordered(items: list[int]) -> list[int], removing duplicates while preserving first-appearance order.
unique_ordered([3, 1, 3, 5, 1, 7]) → [3, 1, 5, 7]
Use a set for the “have I seen this” test — searching a list with in is not acceptable here.
Explain in your notes why the set version is faster.
6-3 Names in common
Implement common(a: list[str], b: list[str]) -> list[str], returning the names that appear in both lists, sorted alphabetically.
common(["Alex","Blake","Chen"], ["Blake","Chen","Dana"]) → ["Blake","Chen"]
6-4 Grouping
Implement group_by_first(words: list[str]) -> dict[str, list[str]], grouping words by their first letter.
group_by_first(["apple","avocado","banana"])
→ {"a": ["apple","avocado"], "b": ["banana"]}
6-5 Parsing a results file
Given several lines of text, each formatted name,subject,score, implement
parse(lines: list[str]) -> dict[str, dict[str, int]],
returning a nested dictionary of {name: {subject: score}}.
parse(["Alex,maths,87", "Alex,physics,92", "Blake,maths,65"])
→ {"Alex": {"maths": 87, "physics": 92}, "Blake": {"maths": 65}}
Note that lines may carry stray whitespace, which you must handle.
6-6 Word frequency
Implement top_words(text: str, n: int) -> list[tuple[str, int]], returning the n most frequent words as (word, count) pairs. Requirements:
- case-insensitive
- strip punctuation from the ends of words (handle at least
.,!?;:) - ties broken alphabetically
top_words("The cat. The DOG! the cat", 2)
→ [("the", 3), ("cat", 2)]
6-7 Choosing a container (no code)
Pick a container for each scenario and write your choice plus a one-sentence reason in your submission notes:
- a mapping from each of 116 student numbers to a name
- every score from one exam, from which you later want the mean and the maximum
- testing whether a word appears in a list of ten thousand common words
- a point on a plane, to be used as a dictionary key
- the set of courses a class is enrolled in, with no course listed twice
- a student’s successive submissions, kept in the order they arrived
Before you submit
- Every function is annotated, with element types spelled out
- The questions in 6-1 and 6-2 are answered in your notes
- 6-4 handles a letter’s first appearance
- 6-5 handles stray whitespace
- 6-6 has been tested with
("The cat. The DOG! the cat", 2) - 6-7 has a reason for every item