Sorting Dictionary Output by Frequency
The source notes that dictionary output may appear random because the keys are stored in hash order rather than in the order in which they were added.
Try it: Counting Words with a Dictionary
The py4e histogram pattern: split each line into words, count them with counts[word] = counts.get(word, 0) + 1, then find the most common word with a max loop or by sorting (count, word) tuples in reverse.
How it works
- Optionally remove punctuation with str.translate and lower-case the line, then split() it into words.
- For each word: counts.get(word, 0) returns the current count or 0 for a new word; store it plus one (or the if word not in counts form).
- A dict remembers insertion order: a word's position is fixed the first time it is seen.
- Max loop: keep the word whose count is strictly larger than the best so far (the first word wins a tie).
- Or build [(count, word) …], sort with reverse=True (ties ordered by the word, reversed) and slice [:N].
Default run (25 steps): Start with an empty dict. The text has 3 lines. … [:3] keeps the top 3: [(5, 'the'), (2, 'sat'), (2, 'on')].
Simplified: Printable-ASCII text up to 320 characters, 8 lines and 60 words, typed in the lab instead of read from a file or URL.
Loading the simulation…
From File Layers to Word Counts
Text in a file arrives in layers. The outer layer consists of lines, and each line contains individual words. Counting every word therefore requires two levels of processing: an outer loop that selects each line and an inner loop that processes the words inside that line. The dictionary records the result by using each word as a key and its frequency as the associated value.
The inner loop completes all of its iterations for one line before the outer loop moves to the next line. This is what allows the program to count every word in every line.
The Two-Level Loop Trace
Imagine an input file containing two lines: 'the cat sat' and 'the dog sat'. The outer loop first selects the line 'the cat sat'. The inner loop then processes 'the', 'cat', and 'sat' in sequence. Only after those three words have been processed does the outer loop select 'the dog sat'. The inner loop then processes 'the', 'dog', and 'sat'.
Building the Counts Dictionary
For each word, the program checks whether that word is already a key in the counts dictionary. If the word is not present, the program adds it with a value of 1. If the word is already present, the program increases its existing value by 1. The if-else structure is important because the first occurrence needs to create the key, while later occurrences need to update the value.
counts = {}
for line in fhand:
words = line.split()
for word in words:
if word not in counts:
counts[word] = 1
else:
counts[word] += 1- 1The outer loop handles the file's line layer.
- 2The inner loop handles the word layer inside the current line.
- 3The membership check chooses between creating a new dictionary entry and updating an existing one.
- 4The complete pattern counts words across all lines processed by the file loop.
- The dictionary starts with no word keys.
- The outer loop receives one line at a time from the file object.
split()produces the words for the current line.- The inner loop processes each word in that list.
- A first occurrence receives the value 1.
- A later occurrence uses the existing value and increments it.
A Complete Count Trace
Tracing Two Input Lines
Count the words in the two lines 'the cat sat' and 'the dog sat'.
- 1First line: the
The word is not yet a key, so the dictionary receives the entry 'the': 1.
- 2First line: cat
The word is new, so the dictionary receives 'cat': 1.
- 3First line: sat
The word is new, so the dictionary receives 'sat': 1. After the first line, the dictionary is {'the': 1, 'cat': 1, 'sat': 1}.
- 4Second line: the
The word is already a key, so its value increases from 1 to 2.
- 5Second line: dog
The word is new, so the dictionary receives 'dog': 1.
- 6Second line: sat
The word is already a key, so its value increases from 1 to 2.
The final dictionary is {'the': 2, 'cat': 1, 'sat': 2, 'dog': 1}.
What do you think happens?
After the first line 'the cat sat' has been processed, what should the dictionary contain?
Reveal answer
{'the': 1, 'cat': 1, 'sat': 1}
Each of the three words has appeared once. The repeated word cases have not occurred yet because the second line has not been processed.
Incrementing Counts Compactly
| Expanded assignment | Compound assignment | Meaning |
|---|---|---|
| counts[word] = counts[word] + 1 | counts[word] += 1 | Read the current value, add 1, and store the result back |
| counts[word] = counts[word] - 1 | counts[word] -= 1 | Subtract from the current value and store the result |
| counts[word] = counts[word] * 1 | counts[word] *= 1 | Multiply the current value and store the result |
| counts[word] = counts[word] / 1 | counts[word] /= 1 | Divide the current value and store the result |
The source identifies +=, -=, *=, and /= as compact assignment operators. The word-counting pattern uses += 1.
From Raw Output to Frequency View
After the nested loops finish, printing the dictionary shows each word as a key and its count as the value. The source notes that dictionary output may appear random because the keys are stored in hash order rather than in the order in which they were added. This does not mean the counting failed: the word-to-count entries are still the important result.
A frequency-oriented view is useful when the goal is to identify the most common words quickly. In the source's Romeo and Juliet example, 'is', 'the', and 'and' appear 3 times, 'sun' appears 2 times, and many other words appear once. The dictionary captures these frequencies, but its unsorted display does not make the most frequent entries easy to spot. Additional processing is therefore needed to present the results in a more readable frequency order.
Control-Flow Mistakes
Common mistake Processing only one word from each line
What it looks likeThe inner loop is missing or is placed outside the outer loop.
Why it failsThe file contains lines, and each line contains multiple words. Without the inner loop, the program does not process every word within each selected line.
Do this insteadUse an outer loop for lines and place the word-processing loop inside it so the inner loop completes for every line.
Common mistake Resetting the dictionary for every line
What it looks likeCreating a new empty counts dictionary inside the outer loop.
Why it failsEarlier line counts would be discarded when the dictionary is recreated for the next line.
Do this insteadKeep one counts dictionary for the complete counting process so entries from earlier lines remain available when later words are processed.
Common mistake Assigning 1 every time a word appears
What it looks likeUsing counts[word] = 1 even when the word is already present.
Why it failsA repeated word would not accumulate its frequency; its existing count would be replaced by 1.
Do this insteadCheck whether the word already exists. Add it with 1 when it is new, and increment its current value when it is repeated.
Common mistake Assuming an apparently random dictionary display means the counts are wrong
What it looks likeExpecting printed keys to appear in the same order as the words were read.
Why it failsThe source explains that dictionary output may appear random because keys are stored in hash order rather than insertion order.
Do this insteadInspect the key-value pairs and use additional organization when you need a frequency-focused display.
Practice the Trace
Trace the input lines 'red blue red' and 'blue green'. Write the dictionary after the first line, then write the final dictionary after the second line. For each word, identify whether the program creates a new key or increments an existing value.
Hints
- Process all three words from the first line before moving to the second line.
- The second occurrence of red should use the existing red entry.
- The second line contains a repeated blue and a new green.
What do you think happens?
After processing both practice lines, which final dictionary is correct?
Reveal answer
{'red': 2, 'blue': 2, 'green': 1}
The first line gives red two occurrences and blue one occurrence. The second line adds one more blue and one green, producing red: 2, blue: 2, and green: 1.
What to Remember
- 1The outer loop processes one file line at a time, while the inner loop processes every word in the selected line.
- 2A dictionary stores each word as a key and its frequency as the value.
- 3A new word receives a count of 1; a repeated word increments its existing count.
- 4counts[word] += 1 is a compact form of counts[word] = counts[word] + 1.
- 5The dictionary contains the frequency data, but additional organization can make the most frequent words easier to identify.
At a glance
- Nested loops navigate the two layers of a text file: lines first, then words within each line.
- The dictionary's keys are words and its values are occurrence counts.
- The if-else structure distinguishes a word's first occurrence from later occurrences.
- The += operator updates an existing count concisely without changing the operation.
- Sorting or organizing the completed dictionary output helps reveal which words occur most frequently.