Home > Software engineering >  Counting the elements in a list of lists using a dictionary
Counting the elements in a list of lists using a dictionary

Time:12-05

How do I convert this list of lists

[['shall', 'prove'], ['shall', 'not'], ['shall', 'go'], ['shall', 'fight'], ['shall', 'fight'], ['shall', 'fight'], ['shall', 'defend'], ['shall', 'fight'], ['shall', 'fight'], ['shall', 'fight'], ['shall', 'fight'], ['shall', 'never']]

into a dictionary which counts how many times each element appears in the list?

i.e. ['shall', 'fight'] appears 7 times

I've tried things like this

def word_counter(input_str):
    counts = {}
    for w in input_str:
        counts[w] = counts.get(w, 0)   1
    items = counts.items()
word_counter([['of', 'god'], ['of', 'his'], ['of', 'her'], ['of', 'god']])

where I'd like the output to be something like

{['of', 'god']: 2, ['of', 'his']: 2, ['of', 'her']: 1}

but I get

TypeError: unhashable type: 'list'

Any help would be much appreciated! Ideally I'd like to do this in basic Python without the need for any extra libraries etc. Thank you

CodePudding user response:

You can convert the list elements into str so you can use them as keys in the dictionary:

def word_counter(input_lst: list[list[str]]) -> dict[str, int]:
    counts: dict[str, int] = {}
    for pair in input_lst:
        pair = str(pair)
        if pair in counts:
            counts[pair]  = 1
        else:
            counts[pair] = 1

    return counts


# Output: {"['of', 'god']": 2, "['of', 'his']": 1, "['of', 'her']": 1}
print(word_counter([['of', 'god'], ['of', 'his'], ['of', 'her'], ['of', 'god']]))

And just convert them back to list if needed.

CodePudding user response:

Lists are mutable objects, they cannot be hashed and thus cannot be used as keys in a dictionary. You can use tuples which are immutable sequences similar to lists. Also, counting is already implemented in python in the collections module in the standard library (you don’t have to install any additional libraries). Here is an example:

import collections

original = [('shall', 'prove'), ('shall', 'not'), ('shall', 'go'), ('shall', 'fight'),
            ('shall', 'fight'), ('shall', 'fight'), ('shall', 'defend'), ('shall', 'fight'),
            ('shall', 'fight'), ('shall', 'fight'), ('shall', 'fight'), ('shall', 'never')]

counts = collections.Counter(original)
# counts is a Counter object which is a subclass of dict, but
# if you want a normal dict add the line below
counts_as_dict = dict(counts)
  • Related