I want to make a function that takes two dictionaries as inputs, where the keys of the dictionaries are strings and the values are ints or floats. It should only use list comprehensions, for-loops, and if statements without imports. for example, an input should look like this:
nearest_location({'person_a': 10, 'person_b': 12},{'place_c': 11, 'place_d': 12})
the goal of this function is to return a single new dictionary comprised of sets of the keys from dictionary 1 and keys from dictionary 2, which are paired based on how close their corresponding values are.
for instance, the input above should return {'person_a': 'place_c', 'person_b': 'place_d'}
. this is because the value for 'person_a'
, 10, in dictionary 1 is closest to the value for 'place_c'
, 11. The same can be said for the values for 'person_b
' and 'place_d'
. Note that the amount of entires in the new dictionary will always be the amount of entries in dictionary 1, regardless of how many entries are in dictionary 2.
Next, I would like to account for loopholes and exceptions in the function:
for example,
nearest_location({'person_a':10, 'person_b':11, 'person_c':12},{'place_a':10,'place_b':10})
should return
({'person_a':'place_a','person_b':'place_a','person_c':'place_a'])
all the values in dictionary 2 are the same, so instead the first key in alphabetical order from dictionary 2 should be paired which each key in dictionary 1 instead.
What I have tried:
the code itself is short and not a function but I wanted to try it as a proof of concept. This method uses a for-loop but I would like to use list comprehension in my function.
people = {'person_a': 10, 'person_b': 12}
places = {'place_c': 11, 'place_d': 12}
for i in people:
for j in places:
print([i, j], abs(people[i] - places[j]))
the output of this is
['person_a', 'place_c'] 1
['person_a', 'place_d'] 2
['person_b', 'place_c'] 1
['person_b', 'place_d'] 0
as you can see, this does not print the dictionary that I want for my functions output. It does however calculate the distance between each key in dictionary 1 and 2. I wanted to use this to somehow get the minimum values an assemble a dictionary from that.
CodePudding user response:
Given the question, I would say a simple solution for this would be
def nearest_location(people, places):
nearest_locations = {}
for i in people:
nearest_dist = float("inf")
nearest_point = None
for place, location in sorted(places.items()):
if (abs(people[i]-location)<nearest_dist):
nearest_dist = abs(people[i]-location)
nearest_point = place
nearest_locations[i]=nearest_point
return nearest_locations
I am not entirely sure what you mean by "It should only use list comprehensions and for-loops without imports". So if we are not allowed to use "if statements", we can do this using list comprehension
def nearest_location(people, places):
nearest_locations = {}
for i in people:
nearest_locations[i] = sorted([(abs(people[i]-location), place) for place, location in places.items()])[0][1]
return nearest_locations
or
def nearest_location(people, places):
return {i:sorted([(abs(people[i]-location), place) for place, location in places.items()])[0][1] for i in people}
CodePudding user response:
def nearest_location(people, places):
assignments = dict()
for person, person_location in people.items():
closest_place, best_distance = '', float('inf')
for place, place_location in places.items():
distance = abs(place_location - person_location)
if distance < best_distance:
closest_place, best_distance = place, distance
elif distance == best_distance:
if place < closest_place:
closest_place = place
assignments[person] = closest_place
return assignments
nearest_location({'person_a':10, 'person_b':11, 'person_c':12},{'place_a':10,'place_b':10})
produces the desired output
{'person_a': 'place_a', 'person_b': 'place_a', 'person_c': 'place_a'}
Whenever, for a given person, there exist two places yielding the same distance, whichever with smaller alphabetical order is used.