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:running\nMary:running\nJohn:dancing\nJack:dancing\nJack:painting\nSmith: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?
CodePudding user response:
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.