pythonlistdictionarypython-3.6set-comprehension

Obtain a set of unique values from a dictionary of lists


I have a list of dictionaries in which the dictionaries also contain a list.

I want to generate a set of the values of the respective nested lists so that I end up with a set of all of the unique items (in this case, hobbies).

I feel a set is perfect for this since it will automatically drop any duplicates, leaving me with a set of all of the unique hobbies.

people = [{'name': 'John', 'age': 47, 'hobbies': ['Python', 'cooking', 'reading']},
          {'name': 'Mary', 'age': 16, 'hobbies': ['horses', 'cooking', 'art']},
          {'name': 'Bob', 'age': 14, 'hobbies': ['Python', 'piano', 'cooking']},
          {'name': 'Sally', 'age': 11, 'hobbies': ['biking', 'cooking']},
          {'name': 'Mark', 'age': 54, 'hobbies': ['hiking', 'camping', 'Python', 'chess']},
          {'name': 'Alisa', 'age': 52, 'hobbies': ['camping', 'reading']},
          {'name': 'Megan', 'age': 21, 'hobbies': ['lizards', 'reading']},
          {'name': 'Amanda', 'age': 19, 'hobbies': ['turtles']},
          ]

unique_hobbies = (item for item in people['hobbies'] for hobby in people['hobbies'].items())

print(unique_hobbies)

This generates an error:

TypeError: list indices must be integers or slices, not str

My comprehension is wrong, but I am not sure where. I want to iterate through each dictionary, then iterate through each nested list and update the items into the set, which will drop all duplicates, leaving me with a set of all of the unique hobbies.


Solution

  • You could also use a set-comprehension:

    >>> unique_hobbies = {hobby for persondct in people for hobby in persondct['hobbies']}
    >>> unique_hobbies
    {'horses', 'lizards', 'cooking', 'art', 'biking', 'camping', 'reading', 'piano', 'hiking', 'turtles', 'Python', 'chess'}
    

    The problem with your comprehension is that you want to access people['hobbies'] but people is a list and can only index lists with integers or slices. To make it work you need to iterate over you list and then access the 'hobbies' of each of the subdicts (like I did inside the set-comprehension above).