Counting how many values were attributed to a key an a python (3.2) dictionary

34,703

Solution 1

One way to solve this, is by changing your last line:

print(key, len([item for item in value if item])) 

So your complete code:

ITEMS = {
    'John greased ': ['axle', 'wheel', 'wheels', 'wheel', 'engine', ''],
    'Paul alleged ': ['truth', 'crime', 'facts', 'infidelity', 'incident', ''],
    'Tracy freed ': ['animals', 'fish', 'slaves', 'slaves', 'slaves', 'pizza'],
    'Lisa plowed ': ['field', 'field', '', '', '', ''],
}

for key, value in ITEMS.items():
    #print value
    print(key, len([item for item in value if item]))

You can also use filter with bool:

print(key, len(filter(bool, value)))

So, the loop:

for key, value in ITEMS.items():
    #print value
    print(key, len(filter(bool, value)))

You need to apply list over filter like so print(key, len(list(filter(bool, value)))) in Python 3.

Solution 2

Use filter with None, it filters out all falsy values from the iterable passed to it.

In Python3 filter returns an iterator so you should call list() on it.:

>>> lis = ['field', 'field', '', '', '', '']
>>> list(filter(None, lis))
['field', 'field']
>>> len(list(filter(None, lis)))
2

Code:

>>> my_dict = {
    'John greased ': ['axle', 'wheel', 'wheels', 'wheel', 'engine', ''],
    'Paul alleged ': ['truth', 'crime', 'facts', 'infidelity', 'incident', ''],
    'Tracy freed ': ['animals', 'fish', 'slaves', 'slaves', 'slaves', 'pizza'],
    'Lisa plowed ': ['field', 'field', '', '', '', ''],
}
for k,v in my_dict.items():
    print (k, len(list(filter(None, v))))
...     
Paul alleged  5
Lisa plowed  2
John greased  5
Tracy freed  6

Timing comparision between filter(None,..) and list comprehension:

>>> lis = ['field', 'field', '', '', '', '']*100
>>> %timeit list(filter(None, lis))
10000 loops, best of 3: 22.2 us per loop
>>> %timeit [item for item in lis if item]
10000 loops, best of 3: 53.1 us per loop
>>> lis = ['field', 'field', '', '', '', '']*10000
>>> %timeit list(filter(None, lis))
100 loops, best of 3: 2.36 ms per loop
>>> %timeit [item for item in lis if item]
100 loops, best of 3: 5.22 ms per loop

Solution 3

data = {
    'John greased ': ['axle', 'wheel', 'wheels', 'wheel', 'engine', ''], 
    'Paul alleged ': ['truth', 'crime', 'facts', 'infidelity', 'incident', ''], 
    'Tracy freed ': ['animals', 'fish', 'slaves', 'slaves', 'slaves', 'pizza'], 
    'Lisa plowed ': ['field', 'field', '', '', '', '']
}

for each in data:
    i = 0
    print each
    for item in data[each]:
        if len(item) > 0:
            i =i +1
    print i
Share:
34,703
user2962024
Author by

user2962024

Updated on July 11, 2022

Comments

  • user2962024
    user2962024 almost 2 years

    I am sure this is silly, but I simply cannot get around it. I have a dictionary, like this, with unequal number of values for each key:

    'John greased ': ['axle', 'wheel', 'wheels', 'wheel', 'engine', ''], 
    'Paul alleged ': ['truth', 'crime', 'facts', 'infidelity', 'incident', ''], 
    'Tracy freed ': ['animals', 'fish', 'slaves', 'slaves', 'slaves', 'pizza'], 
    'Lisa plowed ': ['field', 'field', '', '', '', ''],
    

    I want to know how many values there are for each key, not each unique value but how many tokens there are per key, repeated or not. So I would have a result like:

    John greased  5
    Paul alleged  5
    Tracy freed  6
    Lisa plowed  2
    

    I was trying to use this to work it out using the code bellow:

    for key, value in sorted(result.items()):
             print(key, len(value)) 
    

    But because of the missing values all the lengths turn out to be the same. Any ideas on how to solve this or where to find it out? Thanks a lot for any help.

  • Ashwini Chaudhary
    Ashwini Chaudhary over 10 years
    @GamesBrainiac I am not using lambda here, so this is fine.
  • Games Brainiac
    Games Brainiac over 10 years
    you totally copied my formatted dict! :P Great answer though, I also added that he could use bool instead of None if he so wanted.
  • Ashwini Chaudhary
    Ashwini Chaudhary over 10 years
    @GamesBrainiac filter with None is equivalent to [item for item in iterable if item], so bool is not required.
  • Ashwini Chaudhary
    Ashwini Chaudhary over 10 years
    Okay downvoter fixed the filter call with list().
  • Oleh Prypin
    Oleh Prypin over 10 years
    @GamesBrainiac SyntaxError: invalid syntax, TypeError: object of type 'filter' has no len(), etc.
  • Oleh Prypin
    Oleh Prypin over 10 years
    @hcwhsa Still a bad way to do it.
  • Ashwini Chaudhary
    Ashwini Chaudhary over 10 years
    @OlehPrypin Why? It is faster than the list comprehension based filtering.(I'll add timing comparisons to my answer)
  • Games Brainiac
    Games Brainiac over 10 years
    @OlehPrypin Thats for Python 3. Changed to fix it :)
  • PM0087
    PM0087 over 4 years
    This doesn't work if there is only one entry. If there is only one word, it counts the number of letters of that word.