Counter and defaultdict(int) are very similar, but they are designed for different purposes.
Think of it like this:
defaultdict(int)= A normal dictionary that automatically initializes missing keys to0.Counter= A specialized dictionary designed specifically for counting things, with many built-in counting operations.
1. defaultdict(int)
from collections import defaultdictcount = defaultdict(int)count["apple"] += 1count["banana"] += 1count["apple"] += 1print(count)
Output
defaultdict(<class 'int'>, {'apple': 2, 'banana': 1})
Notice this:
print(count["orange"])
Output
0
No KeyError.
Without defaultdict:
count = {}count["apple"] += 1
Output
KeyError
You would have to write
count["apple"] = count.get("apple", 0) + 1
or
if "apple" not in count: count["apple"] = 0count["apple"] += 1
defaultdict removes this boilerplate.
2. Counter
from collections import Countercount = Counter()count["apple"] += 1count["banana"] += 1count["apple"] += 1print(count)
Output
Counter({'apple': 2, 'banana': 1})
Looks almost identical.
It also returns 0 for missing keys.
print(count["orange"])
0
3. Biggest advantage of Counter
Suppose
words = [ "apple", "banana", "apple", "orange", "apple", "banana"]
Using Counter
from collections import Countercount = Counter(words)print(count)
Output
Counter({ 'apple': 3, 'banana': 2, 'orange': 1})
One line.
Using defaultdict
from collections import defaultdictcount = defaultdict(int)for word in words: count[word] += 1
More code.
4. Counter has many useful methods
most_common()
count = Counter(words)print(count.most_common())
[ ('apple',3), ('banana',2), ('orange',1)]
Top 2
count.most_common(2)
[ ('apple',3), ('banana',2)]
Total count
count.total()
Output
6
Elements
count.elements()
Returns
appleappleapplebananabananaorange
Update
count.update(["apple", "kiwi"])
Result
apple -> 4kiwi -> 1
Subtract
count.subtract(["apple", "banana"])
Now
apple -> 3banana -> 1
5. Mathematical operations
This is where Counter shines.
c1 = Counter(a=3, b=2)c2 = Counter(a=1, b=5)
Addition
c1 + c2
Counter({ 'a':4, 'b':7})
Difference
c1 - c2
Counter({ 'a':2})
Intersection
c1 & c2
Keeps minimum
Counter({ 'a':1, 'b':2})
Union
c1 | c2
Keeps maximum
Counter({ 'a':3, 'b':5})
defaultdict cannot do these operations.
6. Performance
Both are implemented efficiently in C and have similar time complexity for counting.
For counting:
Counter ≈ defaultdict(int)
No meaningful performance difference in most applications.
7. When to use defaultdict(int)
Use it when you’re building a dictionary whose default value is 0, but the dictionary is not necessarily just for counting.
Example:
from collections import defaultdictgraph = defaultdict(list)graph["A"].append("B")graph["A"].append("C")graph["B"].append("D")
Output
{ "A": ["B","C"], "B": ["D"]}
Other common uses:
defaultdict(set)defaultdict(list)defaultdict(dict)
These automatically create empty collections for missing keys.
8. When to use Counter
Use Counter whenever your goal is to answer questions like:
- How many times did each word appear?
- Frequency of characters
- Frequency of IDs
- Top K frequent elements
- Histogram of values
- Counting events
Example:
Counter("mississippi")
Output
{'m':1,'i':4,'s':4,'p':2}
9. Interview examples
Count characters
Counter(s)
Top K Frequent Elements (LeetCode 347)
Counter(nums).most_common(k)
Valid Anagram
Counter(s) == Counter(t)
Group Anagrams
tuple(sorted(Counter(word).items()))
(or more commonly, tuple(sorted(word)) depending on the approach).
Rule of thumb
| Scenario | Use |
|---|---|
| Count frequencies of words, characters, IDs, events | Counter ✅ |
Need most_common(), counting operations, frequency analysis | Counter ✅ |
Build an adjacency list (defaultdict(list)) | defaultdict ✅ |
| Group values by key | defaultdict(list) ✅ |
Need automatic initialization to 0, [], set(), etc. | defaultdict ✅ |
| General-purpose dictionary with default values | defaultdict ✅ |
Simple memory trick
Counter= “I am counting.”defaultdict= “I want a dictionary with automatic default values.”
If you’re solving a frequency-counting problem (common in coding interviews and LeetCode), start with Counter. If you’re building data structures like graphs, groups, or mappings with automatic initialization, use defaultdict.
Leave a comment