I would like to add new keys to an empty dictionary as it goes/reads through my list

Viewed 64

I would like to add new keys to an empty dictionary as it goes/reads through my list. I got this to work when I used a list containing only numbers. However, if I try this with a list which contains strings and numbers I get a KeyError for the first string in the list. Could anyone maybe tell me why this is, or how I can fix it?

di = {}
stuff = ['sun', 20, 20, 14.3, 'sun', 'Flower']
for thing in stuff:
    if thing not in stuff:
        di[thing] = 1
    else:
        di[thing] += 1
print(di)
3 Answers

You're checking for the existence of thing in your list, not in your dictionary.

di = {}
stuff = ['sun', 20, 20, 14.3, 'sun', 'Flower']
for thing in stuff:  # error was here
    if thing not in di:
        di[thing] = 1
    else:
        di[thing] += 1
print(di)

Are you aware of collections.Counter? Counter is a subclass of dict that can do the counting for you.

from collections import Counter
di = Counter(stuff)
print(di)

Your approach is fine if you're still learning, but using Counter is the way to go.

If the task is strictly counting the occurrences then collections.Counter() is the way to go (as @matthias recommends).

A more general way to build a dictionary when you need to alter the key values as you go and where the key may or may not exists is to use the companion collections.defaultdict() or the built in dictionary setdefault().

Your code using setdefault() might look a bit like:

stuff = ['sun', 20, 20, 14.3, 'sun', 'Flower']

di = {}
for thing in stuff:
    di[thing] = di.setdefault(thing, 0) + 1

print(di)

I want to stress though that if you are just looking to count the occurrences of items in a list, collections.Counter() is the way to go and the answer by @matthias is what you want to accept.

Another approach is to use defaultdict

from collections import defaultdict

counter = defaultdict(int)
stuff = ['sun', 20, 20, 14.3, 'sun', 'Flower']
for s in stuff:
  counter[s] +=1 
print(counter)

output

defaultdict(<class 'int'>, {'sun': 2, 20: 2, 14.3: 1, 'Flower': 1})
Related