Как найти рейтинг в таблице лидеров и превратить его в словарь в Python 3? - PullRequest
0 голосов
/ 18 мая 2018

У меня есть вложенная таблица лидеров, например:

[[100, 100, 50, 40, 40, 20, 10, 5], [100, 100, 50, 40, 40, 25, 20, 10]]

Я хочу найти рейтинг в этой таблице лидеров в методе ранжирования плотного порядка.https://en.wikipedia.org/wiki/Ranking#Dense_ranking_.28.221223.22_ranking.29

И я хочу использовать ранжирование и превратить его в словарь, но оценки должны оставаться в качестве ключей, а ранжирование - в качестве значений, например:

[{100:1,100:1,50:2,40:3,40:3,20:4,10:5,5:6},{100:1,100:1,50:2,40:3,40:3,25:4,20:5,10:6}]

Как я могу добиться этого с помощью Python3?

Ответы [ 2 ]

0 голосов
/ 18 мая 2018

Менее производительное, но сжатое решение возможно с использованием словаря и списков:

lst = [[100, 100, 50, 40, 40, 20, 10, 5], [100, 100, 50, 40, 40, 25, 20, 10]]

dicts = [{v: k for k, v in dict(enumerate(reversed(sorted(set(i))), 1)).items()}\
         for i in lst]

res = [[(n, dicts[i][n]) for n in j] for i, j in enumerate(lst)]

Для производительности я рекомендую использовать стороннюю библиотеку, такую ​​как numpy или pandas:

import pandas as pd

data = pd.DataFrame(lst).T
ranks = data.rank(method='dense', axis=0, ascending=False).astype(int)

res = [list(zip(data[i], ranks[i])) for i in range(len(data.columns))]

[[(100, 1), (100, 1), (50, 2), (40, 3), (40, 3), (20, 4), (10, 5), (5, 6)],
 [(100, 1), (100, 1), (50, 2), (40, 3), (40, 3), (25, 4), (20, 5), (10, 6)]]
0 голосов
/ 18 мая 2018

Как уже упоминалось, ожидаемая структура данных не является словарем, поскольку содержит дубликаты ключей.Вместо этого вы можете создать список кортежей.Вы можете использовать объект счетчика и словарь для отслеживания видимых элементов и их соответствующего индекса для создания этого кортежа.

Следующая функция представляет собой понятную реализацию вышеупомянутого метода, который создает ожидаемый результат за одну итерацию.

In [38]: from itertools import count
In [38]: def ranker(lst):
    ...:     for sub in lst:
    ...:         seen = {}
    ...:         c = count()
    ...:         next(c)
    ...:         ss = []
    ...:         for j in sub:
    ...:             try:
    ...:                 ind = seen[j]
    ...:             except KeyError:
    ...:                 ind = seen[j] = next(c)
    ...:             ss.append((j, ind))
    ...:         yield ss

Демонстрация:

In [39]: lst
Out[39]: [[100, 100, 50, 40, 40, 20, 10, 5], [100, 100, 50, 40, 40, 25, 20, 10]]

In [40]: list(ranker(lst))
Out[40]: 
[[(100, 1), (100, 1), (50, 2), (40, 3), (40, 3), (20, 4), (10, 5), (5, 6)],
 [(100, 1), (100, 1), (50, 2), (40, 3), (40, 3), (25, 4), (20, 5), (10, 6)]]

Теперь еще один очень питонский, но немного неясный подход состоит в том, чтобы вместо использования блоков counter и try-except и даже списка и добавленияиспользуя метод dict.setdefault() в понимании списка следующим образом:

In [43]: def ranker(lst):
    ...:     for sub in lst:
    ...:         seen = {}
    ...:         yield [(j, seen.setdefault(j, len(seen) + 1)) for j in sub]

Метод dict.setdefault() возвращает соответствующее значение для первого аргумента, если он присутствует в словаре, в противном случае обновляется со вторым аргументом (len(seen) + 1) в качестве значения и возвращает его.

Демо:

In [44]: list(ranker(lst))
Out[44]: 
[[(100, 1), (100, 1), (50, 2), (40, 3), (40, 3), (20, 4), (10, 5), (5, 6)],
 [(100, 1), (100, 1), (50, 2), (40, 3), (40, 3), (25, 4), (20, 5), (10, 6)]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...