user2978216
user2978216

Reputation: 568

Counter() and string formatting

The issue can be solved in many ways but this question is about polymorphism. Is it possible to polymorph Counter() class so when there is no such key in Counter() instance string formatting would return 0? Basically is needed to make the last line of the code to work.

from collections import Counter
VOWELS = 'aeiou'
context = 'Computing is cool'
cnt = Counter()
for letter in context:
    if letter in VOWELS:
        cnt[letter] += 1    
print('o-{o}, i-{i}, o-{o}'.format(**cnt))

# I'd like to make this line to work :
#print('a-{a}, e-{e}, i-{i}, o-{o}, u-{u}'.format(**cnt))

Output:

o-3, i-2, u-1

Desirable output:

a-0, e-0, i-2, o-3, u-1

Upvotes: 1

Views: 667

Answers (2)

user2357112
user2357112

Reputation: 280887

This isn't a case for changing the Counter. ** unpacking converts your Counter to a regular dict, which does not have a default value of 0 for missing keys. (At least, it converts your Counter now; there was a bug on earlier versions, so if you try the ** code on an earlier Python version and it seems to work, that's why.)

Instead of **, use format_map, which will use your Counter directly:

print('o-{o}, i-{i}, o-{o}'.format_map(cnt))

Upvotes: 4

Dimitris Fasarakis Hilliard
Dimitris Fasarakis Hilliard

Reputation: 160447

when there is no such key in Counter() instance string formatting would return 0?

but that's not the issue here. The issue is that **cnt will only unpack the existing elements.

What you can do is initialize the counter with zero counts for all VOWELS and then unpack:

cnt = Counter({i:0 for i in 'aeiou'})

now the unpacking will pick these elements up, even if they have a 0 count. After the loop executes, print:

print('a-{a}, e-{e}, i-{i}, o-{o}, u-{u}'.format(**cnt))

will return your wanted result:

a-0, e-0, i-2, o-3, u-1

Upvotes: 1

Related Questions