Counter vs Defaultdict

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 to 0.
  • Counter = A specialized dictionary designed specifically for counting things, with many built-in counting operations.

1. defaultdict(int)

from collections import defaultdict
count = defaultdict(int)
count["apple"] += 1
count["banana"] += 1
count["apple"] += 1
print(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"] = 0
count["apple"] += 1

defaultdict removes this boilerplate.


2. Counter

from collections import Counter
count = Counter()
count["apple"] += 1
count["banana"] += 1
count["apple"] += 1
print(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 Counter
count = Counter(words)
print(count)

Output

Counter({
'apple': 3,
'banana': 2,
'orange': 1
})

One line.

Using defaultdict

from collections import defaultdict
count = 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

apple
apple
apple
banana
banana
orange

Update

count.update(["apple", "kiwi"])

Result

apple -> 4
kiwi -> 1

Subtract

count.subtract(["apple", "banana"])

Now

apple -> 3
banana -> 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 defaultdict
graph = 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

ScenarioUse
Count frequencies of words, characters, IDs, eventsCounter
Need most_common(), counting operations, frequency analysisCounter
Build an adjacency list (defaultdict(list))defaultdict
Group values by keydefaultdict(list)
Need automatic initialization to 0, [], set(), etc.defaultdict
General-purpose dictionary with default valuesdefaultdict

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