Home > other >  Python Rank values from closest to target
Python Rank values from closest to target

Time:04-26

I have a problem. In my code I have the following dictionary:

dict = {}
dict['A'] = {'slope': -51, 'score': 0}
dict['B'] = {'slope': 12, 'score': 0}
dict['C'] = {'slope': -4, 'score': 0}
dict['D'] = {'slope': -31, 'score': 0}
target = -21

The dictionary isn't sorted! Now what I am trying to do is, give each item in the dict a score (1 to 4). The dict closest to the target gets 4 points, the next one 3 points, etc.

First I thought I iterate over the dict values, but then I realised that I don't know which if there are values closer than the current one, so I can't keep the score about that.

In the end, it needs to look like this:

{'A': {'slope': -51, 'score': 2}, 'B': {'slope': 12, 'score': 1}, 'C': {'slope': -4, 'score': 3}, 'D': {'slope': -31, 'score': 4}}

What can I do to achieve this?

CodePudding user response:

Sort the items of the dictionary by distance from the target in descending order. Then, the index of the item plus one is the number of points it should get:

sorted_items = sorted(state.items(),
    key=lambda x: abs(x[1]['slope'] - target), reverse=True)

for idx, (key, _) in enumerate(sorted_items, start=1):
    state[key]['score'] = idx
    
print(state)

This outputs:

{
 'A': {'slope': -51, 'score': 2},
 'B': {'slope': 12, 'score': 1},
 'C': {'slope': -4, 'score': 3},
 'D': {'slope': -31, 'score': 4}
}

I've renamed dict to state here, because dict is the name of a Python builtin.

CodePudding user response:

First, don't call your dictionaries dict, because dict is the name of the builtin dictionary class.

d = {}
d['A'] = {'slope': -51, 'score': 0}
d['B'] = {'slope': 12, 'score': 0}
d['C'] = {'slope': -4, 'score': 0}
d['D'] = {'slope': -31, 'score': 0}
target = -21

Now, you can sort the keys of the dict based on how far the slope value is from target:

>>> sorted_keys = sorted(d.keys(), key=lambda k: abs(d[k]['slope'] - target))
['D', 'C', 'A', 'B']

Then, you can assign scores:

num_keys = len(sorted_keys)
for key, score in zip(sorted_keys, range(num_keys, 0, -1)):
    d[key]['score'] = score

Which gives you this d:

{'A': {'slope': -51, 'score': 2},
 'B': {'slope': 12, 'score': 1},
 'C': {'slope': -4, 'score': 3},
 'D': {'slope': -31, 'score': 4}}

CodePudding user response:

You can sort the values of the dict.

Note: don't call your dict like that, since it is the name of a native function.

d = {
  'A': {'slope': -51, 'score': 0},
  'B': {'slope': 12, 'score': 0},
  'C': {'slope': -4, 'score': 0},
  'D': {'slope': -31, 'score': 0}
}
target = -21

for i, item in enumerate(sorted(d.values(), key=lambda x: abs(target - x["slope"]),
                                            reverse=True), 1):
    item["score"] = i

print(d)
  • Related