Find keys in dictionary with values that intersect with list

Question:

I need to write a function that finds all different people who have at least one of the given hobbies. The function returns a set of these names. I thought it would be logical to turn the string into a dictionary, and then compare dictionary values with what is in hobbies. I got the following:

def find_people_with_hobbies(data: str, hobbies: list) -> set:
    new_dict = create_dictionary(data) # creates a dictionary in the form {name1: [hobby1, hobby2, ...], name2: [...]}
    return set([k for k, v in new_dict.items() if v == hobbies])

So, given data="John:runningnMary:runningnJohn:dancingnJack:dancingnJack:paintingnSmith:painting" and hobbies=["running", "dancing"], the result should be {"John", "Mary", "Jack"}. In my case, it only finds Jack. How can this be improved/fixed?

Asked By: QLimbo

||

Answers:

The problem is with the comparison between v and hobbies, i.e. the snippet v == hobbies. In your example, find_people_with_hobbies only returns "Jack" because Jack has exactly the hobbies in hobbies.

You should rather take the intersection of v and hobbies and check that it is not empty. You can do that with sets:

def find_people_with_hobbies(data: str, hobbies: list) -> set:
    new_dict = create_dictionary(data) # creates a dictionary in the form {name1: [hobby1, hobby2, ...], name2: [...]}
    return set([k for k, v in new_dict.items() if set(v).intersection(hobbies)])

In addition, you could have create_dictionary create a dictionary with sets as values. That way you would not have to construct a set, set(v), and could just do v.intersection(hobbies). A set makes sense after all, since each hobby cannot be present more than once.

Answered By: Sebastian Baltser
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.