-1

How to find the rank of the user by value.

data = [
        {
            "playerId": 2,
            "value": 196763.8
        },
        {
           "playerId": 3,
           "value": 196763.8
        },
        {
           "playerId": 44,
           "value": 196764
        }
]

I have tried:

index = [ x['playerId'] for x in data ].index(3) #3 playerId
rank = index+1

I am getting rank is: 2

Rank should be 1 for playerId 2 and 3 (because value are same 196763.8 ) and for playerId 44 rank will be 2

Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
dev
  • 152
  • 1
  • 10

2 Answers2

0

You need to sort the list by value and also find if some player_id have same score as others and combine them into one.

This should do the trick:

from collections import defaultdict

new_dict = defaultdict(list)
for x in data:
    new_dict[x['value']].append(x['playerId'])  

rank_list = [[k,v] for k,v in new_dict.items()]
# Set reverse=False if lower score is considered higher rank
rank_list.sort(key=lambda k: k[0], reverse=True) 
def get_rank(player_id):
    for i in range(len(rank_list)):
        if player_id in rank_list[i][1]:

            return i+1 # list is 0 indexed thus +1

print('Rank is %s for player id %s' % (get_rank(44), 44))
> Rank is 1 for player id 44
print('Rank is %s for player id %s' % (get_rank(2), 2))
> Rank is 2 for player id 2
print('Rank is %s for player id %s' % (get_rank(3), 3))
> Rank is 2 for player id 3


alikhtag
  • 316
  • 1
  • 6
  • A couple comments: the key parameter is not needed if you store the items as a sequence whose first element is the score (like you did here), the default behavior is to order by the first item in the sequence, draws by second item, etc but as you don't have draws as you already merged them, you are set without that parameter. Also, I would suggest using a tuple: `rank_list = [(k,v) for k,v in new_dict.items()]` as you don't need mutability. – Adirio Mar 02 '20 at 11:53
  • Even further, `rank_list = sorted(new_dict.items(), reverse=True)` should do the trick instead of using a list comprehension and then sorting, and this way it will be a bit more memory efficient. – Adirio Mar 02 '20 at 11:57
0

You can use pandas, i.e.:

df = pd.DataFrame(data)
df['rank'] = df['value'].rank(ascending=True, method="min").astype(int)
df = df.sort_values(by=['rank']).reset_index(drop=True)
for i in range(1, len(df)):
    last, curr = df.loc[i-1, 'rank'], df.loc[i, 'rank']
    df.loc[i, 'rank'] = last + 1 if last < curr else last

print(df)

   playerId     value  rank
0         2  196763.8     1
1         3  196763.8     1
2        44  196764.0     2

Demo

Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268