How to create a dictionary from a string returning the number of characters
I want a string such as 'ddxxx'
to return like ('d': 2, 'x': 3)
. So far I've tried
result = {}
for i in s:
if i in s:
result[i] += 1
else:
result[i] = 1
return result
where s
is a string, however I keep getting KeyError
. For example. if i put s
like 'hello'
then the returned error is:
result[i] += 1
KeyError: 'h'
source to share
The problem is with your second condition. if i in s
checks for a character in the string itself, not in the dictionary. It should be if i in result.keys()
or as mentioned Neil It could be simpleif i in result
Example:
def fun(s):
result = {}
for i in s:
if i in result:
result[i] += 1
else:
result[i] = 1
return result
print (fun('hello'))
This will print
{'h': 1, 'e': 1, 'l': 2, 'o': 1}
source to share
This can be easily solved using collections.Counter
. A counter is a subtype of the standard dictation that is done to count things. It will automatically make sure that indexes are created when you try to increment something that was not previously in the dictionary, so you don't have to check it yourself.
You can also pass any iterable value to the constructor so that it automatically counts occurrences of elements in that iterable. Since a string is character iterable, you can simply pass your string to it to count all characters:
>>> import collections
>>> s = 'ddxxx'
>>> result = collections.Counter(s)
>>> result
Counter({'x': 3, 'd': 2})
>>> result['x']
3
>>> result['d']
2
Of course, doing it manually is fine too, and your code is almost perfect for that. Since you are getting KeyError
, you are trying to access a key in the dictionary that doesn't exist. This happens when you come to a new character that you did not consider before. You have already tried to deal with this with validation if i in s
, but you are testing containment for the wrong reason. s
is your string, and since you are repeating a i
string character i in s
will always be true. Instead, you want to check if i
as a key exists in the dictionary result
. Because if it doesn't add it as a new account key 1
:
if i in result:
result[i] += 1
else:
result[i] = 1
source to share
Usage collections.Counter
is a smart decision. But if you want to reinvent the wheel, you can use a method dict.get()
that allows you to specify a default for missing keys:
s = 'hello'
result = {}
for c in s:
result[c] = result.get(c, 0) + 1
print result
Output
{'h': 1, 'e': 1, 'l': 2, 'o': 1}
source to share