Python Порядковый ранг - PullRequest
0 голосов
/ 11 марта 2020

Доброе утро, пожалуйста, у меня есть таблица, в которой я пытаюсь вернуть позиции (ранги) баллов студентов. Я искал везде, и я не получаю ничего лучше. Я думал, что смогу сделать это с помощью сортировки, но это не так. Это таблица:

Name       Score    Position 

David      89        3rd
James      56        5th
Matt       72        4th
John       91        1st
Iva        56        5th
Anna       91        1st

Я пытался написать этот код, но он не заботится о дубликатах

score = [89, 56, 72, 91, 56,91]
order = sorted(list(set(score)), reverse=True)
position = []

for n in score:
     position.append(order.index(n) + 1)

print(position)

Ответы [ 4 ]

1 голос
/ 11 марта 2020

Вы можете использовать defaultdict для хранения результатов и индексов в исходном списке, чтобы иметь дело с дубликатами:

from collections import defaultdict                                                   

scores_dict = defaultdict(list)                                                      
for i, s in enumerate(scores): 
    scores_dict[s].append(i)

positions = [None] * len(scores)
rank = 1                                                                             
for s in sorted(scores_dict, reverse=True): 
    indices = scores_dict[s] 
    for i in indices: 
        positions[i] = rank 
    rank += len(indices)
1 голос
/ 11 марта 2020

Если вы хотите использовать внешнюю библиотеку, я могу порекомендовать только ranking:

import ranking

# Each player and their scores.
score_list = [
    ('David', 89),
    ('James', 56),
    ('Matt', 72),
    ('John', 91),
    ('Iva', 56),
    ('Anna', 91),
]

# Helper for accessing a score record's score, 
# defined here as we need it twice.
get_score = lambda pair: pair[1]

# Sort the scores in place; required by `ranking`.
score_list.sort(key=get_score, reverse=True)

# Define a format string; handy for formatting both the header and the scores.
format_str = "{player:10}   {score:<10}   {rank}"

# Print header.
print(format_str.format(player="Player", score="Score", rank="Position"))

# Rank and print.
for rank, (player, score) in ranking.Ranking(score_list, key=get_score, start=1):
    print(format_str.format(rank=rank, player=player, score=score))

выходы

Player       Score        Position
John         91           1
Anna         91           1
David        89           3
Matt         72           4
James        56           5
Iva          56           5
1 голос
/ 11 марта 2020

Если вы ищете простое решение без использования каких-либо библиотек:

score = [89, 56, 72, 91, 56, 91]

sorted_score = sorted(score, reverse=True)
position = [1]
pos = 1
for i in range(1, len(score)):
    if sorted_score[i] < sorted_score[i-1]:
        pos = i+1
    position.append(pos)

print(position)
[1, 1, 3, 4, 5, 5]
1 голос
/ 11 марта 2020

Не самый лучший код, но я думаю, что это сделано, что вы просите:

from collections import Counter

score = [89, 56, 72, 91, 56, 91]

score_set = sorted(list(set(score)), reverse=True) # unique score
dico = dict((v, i + 1) for i, v in enumerate(score_set)) # position of unique score
count = Counter(score) # occurence of each score
total = 1 # indice to get the current position in the score

# update the dico by counting the number of duplicate.
for k, v in sorted(dico.items(), key=lambda x: x[1]): # sort the dico by the value (rank without duplicate)
        count_ = count[k]
        dico[k] = total
        total += count_ # take into account potential duplicate

position = [dico[e] for e in score]  # apply the dict to our original list

print(position) # et voilà
...