1

I‘ve got a dictionary with multiple values for each key. Therefore I‘m using a list for the values. Now I want to count how often a value occurs in this list of values. For example I‘ve got the following dictionary:

dic = {}
dic.setdefault(„Sam“, []).append(„Smith“)
dic.setdefault(„Sam“, []).append(„Miller“)
dic.setdefault(„Sam“, []).append(„Smith“)

So

for k, v in dic.items():
    print(k,v)

results in:

  Sam [Smith, Miller, Smith]

Now I want to count how often each value occurs and print the frequency next to the value itself. I want the output to look like the following:

Smith: 2, Miller: 1

For that purpose I‘ve tried the following code without success:

D = defaultdict(list)
for i, item in enumerate(mylist):
    D[item].append(i)
D = {k: len(v) for k, v in D.items()}
print(D)

This code just works fine for a simple list like:

mylist = [10, 20, 30, 10, 30]

For such a kind of list the code above will result in what I expect:

{10: 2, 30:2, 20:1}

However it won‘t work with the list containing the values. Instead it shows the following error message when using „dic“ instead of „mylist“ in the 2nd line:

TypeError: unhashable type: 'list'

Would be great if someone could help.

monpy
  • 75
  • 1
  • 2
  • 6
  • A key needs to be immutable. Convert the list to a tuple. – Peter Wood Nov 30 '15 at 20:42
  • Possible duplicate of [Python, TypeError: unhashable type: 'list'](http://stackoverflow.com/questions/19371358/python-typeerror-unhashable-type-list) – Peter Wood Nov 30 '15 at 20:42
  • No, I don't think it's because he's using a list rather than a tuple here. It's because he's trying to count the wrong thing - he needs to count frequencies in the values (which can be a list), not the items of the dict – zehnpaard Nov 30 '15 at 20:45
  • @zehnpaard `D[item]` where `D` is a `dict` and `item` is a `list`. `D[tuple(item)]` would work. – Peter Wood Nov 30 '15 at 23:12
  • @PeterWood Right, it would work in that it won't throw an exception, but the output isn't what's being looked for here (counting the frequencies of the things within the lists). – zehnpaard Dec 01 '15 at 07:36

1 Answers1

1

That's actually a pretty interesting way of creating a "Count" feature. The issue is that your code counts items in lists, so passing a dictionary to it won't work. Instead, you should pass the values from your dic.items(). If we use what you have:

for k, v in dic.items():
    D = defaultdict(list)
    for i, item in enumerate(v):
        D[item].append(i)
    D = {k: v for k, v in D.items()}
    print(k, D)

Also, take a look at collections.Counter which is a standard library implementation of Count.

from collections import Counter
for k, v in dic.items():
    print(k, Counter(v))
zehnpaard
  • 6,003
  • 2
  • 25
  • 40
  • Thank you very much @zehnpaard. That's exactly what I was looking for and both solutions just do what they are supposed to do. Seeing how easy this actually was makes me feel really silly now. By the way, I've edited my initial question as I wanted to write `D = {k: len(v)for k, v in D.items()}`. With that additional `len()` in your first solution it works brilliantly. Much appreciated! – monpy Dec 01 '15 at 07:30