2

Suppose I have a dict with the contents as follows:

leaderboard = {"James": 4, "Tom": 2, "Tim": 8, "Jim": 2}

How would I go about getting a rank for each name, so that people with the same scores have the same rank?

  Tim: 1
James: 2
  Tom: 3
  Jim: 3
avinashbot
  • 1,177
  • 1
  • 11
  • 25
  • what rank do you want to give if there is a fifth person with the lowest value? – Padraic Cunningham May 13 '14 at 20:59
  • Well, giving the person a rank 4 is much easier in python than giving him a rank 5, so that's what I'm going with. – avinashbot May 13 '14 at 21:03
  • 1
    @seefour Typically, you would assign 5. Rank is a measure of how many people are ahead of you. Both Tom and Jim have only 2 people ahead of them (neither of the two is ahead of the other), but anyone behind Tom or Jim will certainly have 4, not just 3, people ahead of them. – chepner May 13 '14 at 21:43
  • solution for this case here: http://stackoverflow.com/questions/32908613/ranking-values-in-a-dictionary-and-taking-care-of-ex-aequos-correctly – beta Oct 02 '15 at 14:18

3 Answers3

2

just sort the items by value, loop over them and increase the rank only if the value is strictly smaller than the previous one.

Pavel
  • 7,436
  • 2
  • 29
  • 42
1

You're looking at inversing the mapping from names:ranks to ranks:names. https://stackoverflow.com/a/485368/183948 has your answer.

inv_map = {}
for k, v in leaderboard.items():
    inv_map[v] = inv_map.get(v, [])
    inv_map[v].append(k)

After which, you can sort this inv_map's values to get what you're looking for.

Community
  • 1
  • 1
Brad Beattie
  • 579
  • 3
  • 13
  • 1
    Thanks. I ended up using this along with `ranked = []` `for key in sorted(inv_map, reverse=True):` `ranked.append(inv_map[key])` to sort the dict. – avinashbot May 13 '14 at 21:00
0

You can use the built in sorted function as well as a lambda function to sort the dictionary by the value instead of the dictionary key. Then we can simply go through a for loop to assign ranks. This code is probably not optimized but it works, you can maybe find out how to optimize the for loop on you own. The ranked dict will hold the peoples rank, you could also put this into a list if you wanted too.

sorted_by_value = sorted(learderboard, key = lambda x: leaderboard[x], reverse = True)

rank = 1
last_value = leaderboard[sorted_by_value[0]]
ranked_dict = dict()
for name in sorted_by_value:
    this_value = leaderboard[name]
    if this_value != last_value:
        rank += 1
    ranked_dict[name] = rank
    last_value = this_value
Elias
  • 1,367
  • 11
  • 25