Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create a dictionary from a string returning the number of characters [duplicate]

I want a string such as 'ddxxx' to be returned as ('d': 2, 'x': 3). So far I've attempted

result = {}
for i in s:
    if i in s:
        result[i] += 1
    else:
        result[i] = 1
return result   

where s is the string, however I keep getting a KeyError. E.g. if I put s as 'hello' the error returned is:

result[i] += 1
KeyError: 'h'
like image 321
tribo32 Avatar asked Dec 27 '14 10:12

tribo32


4 Answers

The problem is with your second condition. if i in s is checking for the character in the string itself and not in the dictionary. It should instead be if i in result.keys() or as Neil mentioned It can just be if 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 would print

{'h': 1, 'e': 1, 'l': 2, 'o': 1}
like image 65
Bhargav Rao Avatar answered Oct 16 '22 18:10

Bhargav Rao


You can solve this easily by using collections.Counter. Counter is a subtype of the standard dict that is made to count things. It will automatically make sure that indexes are created when you try to increment something that hasn’t been in the dictionary before, so you don’t need to check it yourself.

You can also pass any iterable to the constructor to make it automatically count the occurrences of the items in that iterable. Since a string is an iterable of characters, you can just 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 the manual way is fine too, and your code almost works fine for that. Since you get a KeyError, you are trying to access a key in the dictionary that does not exist. This happens when you happen to come accross a new character that you haven’t counted before. You already tried to handle that with your if i in s check but you are checking the containment in the wrong thing. s is your string, and since you are iterating the character i of the string, i in s will always be true. What you want to check instead is whether i already exists as a key in the dictionary result. Because if it doesn’t you add it as a new key with a count of 1:

if i in result:
    result[i] += 1
else:
    result[i] = 1
like image 35
poke Avatar answered Oct 16 '22 20:10

poke


Using collections.Counter is the sensible solution. But if you do want to reinvent the wheel, you can use the dict.get() method, which allows you to supply a default value 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}
like image 2
PM 2Ring Avatar answered Oct 16 '22 19:10

PM 2Ring


Here is a simple way of doing this if you don't want to use collections module:

>>> st = 'ddxxx'
>>> {i:st.count(i) for i in set(st)}
{'x': 3, 'd': 2}
like image 1
Irshad Bhat Avatar answered Oct 16 '22 19:10

Irshad Bhat