3

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.

MSeifert
  • 145,886
  • 38
  • 333
  • 352
MarkS
  • 1,455
  • 2
  • 21
  • 36

2 Answers2

1

I got it:

unique_hobbies = set()

for d in people:
    unique_hobbies.update(d['hobbies'])

print(unique_hobbies)
mattjegan
  • 2,724
  • 1
  • 26
  • 37
MarkS
  • 1,455
  • 2
  • 21
  • 36
1

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).

MSeifert
  • 145,886
  • 38
  • 333
  • 352
  • This answers my question, but I have a follow up, if I may. It works, but PyCharm is throwing a warning which I don't get since your comprehension is working. The warning is: Expected 'collections.iterable', got 'Union[str, int, List[str]]' instead. – MarkS Aug 02 '17 at 10:31
  • Not sure what that means because the `'hobbies'` are all `List[str]`. Maybe PyCharm is confusing something with the other dictionary entries (which would be `str` for name and `int` for age). – MSeifert Aug 02 '17 at 10:32