Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
The Standard Toolbox  ›  Lesson

Collections: Counter, defaultdict, namedtuple, OrderedDict

Collections 16 minFour dict/tuple upgrades that solve one repeated pattern each
Your task
Write word_tally(words): count how many times each word appears with Counter, and return the top 3 most common as a list of [word, count] pairs, most frequent first (ties keep first-seen order). Example: word_tally(["a", "b", "a", "c", "b", "a"]) -> [["a", 3], ["b", 2], ["c", 1]].

Collections: Counter, defaultdict, namedtuple, OrderedDict

In short: collections ships four small upgrades on dict and tuple, each solving one pattern you'd otherwise write by hand. Counter tallies hashable things and returns 0 instead of raising on a key you never saw. defaultdict fills in a missing key's starting value automatically, so groups[key].append(x) just works on the first hit. namedtuple gives a plain tuple's fields real names instead of magic indices, and OrderedDict is a dict that remembers arrival order and can move a key back to the front on demand. Reach for one of these before you hand-roll the same three lines again.

A shelf of four labelled boxes — Counter holding tally marks, defaultdict with an empty list already waiting inside, namedtuple as a tuple with name tags on each slot, OrderedDict as a numbered queue with one item moved to the back

Count votes in a poll

Four candidates, one vote per line. Counting by hand with a plain dict fails the moment a name shows up for the first time:

What happens when you run this?
votes = ["A", "B", "A", "C", "A", "B"]

counts = {}
for v in votes:
    counts[v] += 1
print(counts)

Counter is a dict built for exactly this — every key starts at 0, so += 1 just works, and it comes with .most_common() for free:

python

Counter is a dict (isinstance(tally, dict) is True), so every dict method still works. .most_common() and the arithmetic (Counter(...) + Counter(...), -, &, |) are what it adds.

Roll call by class

A school's enrolment list pairs each student with their class. Grouping students by class is the same missing-key problem, one level up:

broken — fix itKeyError

Run it and read which class crashes first. Then swap the plain dict for a defaultdict(list).

defaultdict(list) takes a factory — a function called with no arguments to build the missing value. list makes [], int makes 0, and you can pass your own function too. Once a roll is grouped, give each row real field names instead of a bare tuple:

python

Keep a recent-orders log in order

A kitchen screen shows orders in the sequence they arrived, and "bump" moves a reopened order back to the front of the queue. A plain dict already remembers insertion order since Python 3.7 — but it has no way to change an item's position without deleting and re-adding it. OrderedDict adds exactly that:

python

The one-word difference from a plain dict that trips people up is equality:

What does this print?
from collections import OrderedDict

a = OrderedDict([("x", 1), ("y", 2)])
b = OrderedDict([("y", 2), ("x", 1)])
print(a == b)

Quick practice

What does this print?
from collections import Counter

bag = Counter("mississippi")
print(bag.most_common(1))
broken — fix it

Run it and see every total stuck at 0. Fix the line that's supposed to add up the prices.

What does this print?
from collections import namedtuple

Point = namedtuple("Point", "x y")
p = Point(3, 4)
print(p[0] + p.y)

🎯 Your turn

Write word_tally(words): count how many times each word appears, and return the top 3 most common as a list of [word, count] pairs, most frequent first (ties keep the order the words first appeared in).

  • word_tally(["a", "b", "a", "c", "b", "a"]) → [["a", 3], ["b", 2], ["c", 1]]
  • word_tally([]) → []

Hint: Counter(words).most_common(3) returns a list of (word, count) tuples — turn each one into a list with [list(pair) for pair in ...].

Press ▶ Run and hit ✓ Check. ✅

Practice — level up

0/5 solved

Solve each in its own editor — Run to try, Check to grade. Stuck? Reveal a Hint, or the full Solution + walkthrough.

Warm-upThe most common character

Write most_frequent_char(s) returning the single most common character in s (ties go to whichever appeared first).

counter
DrillGroup words by length

Write group_by_length(words) returning a dict mapping each length (as a string, e.g. "3") to the list of words with that length, in the order they appeared. Use defaultdict(list).

defaultdict
BuildThe closest point to home

Define Point = namedtuple("Point", "x y"). Write closest_point(points): given a list of [x, y] pairs, build a Point for each and return the [x, y] of the one closest to the origin (0, 0) (ties go to whichever came first).

namedtuple
BossCount and total by tag

Write tag_report(items): items is a list of [tag, value] pairs. Return a dict mapping each tag to {"count": n, "total": sum}, in the order each tag first appeared.

counterdefaultdict
CapstoneA recently-viewed list with a size limit

Write recent_unique(ids, keep=3): replay ids one at a time into an OrderedDict. Seeing an id again moves it to the end (most recent); a new id is added at the end; once there are more than keep ids, drop the oldest one. Return the final ids, oldest to newest.

ordereddict
word_tally.py
Call the function you wrote — just like your app's frontend would. Edit the inputs and hit Call.
word_tally(words) → listCount every word, return the top 3 most common as [word, count] pairs.
try:
returned
No app map for this section yet.
Press Run to execute your code.
Press Check to run the tests for this lesson.