Печатать верхние "n" записи в словаре
Здесь мой текущий код
pN ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
highestCount = max(pN.values())
for k, v in pN.items():
if v == highestCount:
print(v,k)
Однако это только печатает верхнего пользователя и, если эта позиция является общей, печатает ее снова как таковой
10 dave
10 jacinta
Мне нужно иметь возможность печатать любое количество лучших пользователей (n
) и форматировать их как таковые, например, для n = 5
:
10 john, jacinta,
8 james
6 john
3 jack
2 sam
Ответы
Ответ 1
Используйте команду collections.defaultdict
, поменяйте свои keys
и values
from collections import defaultdict
dct = defaultdict(list)
for k, v in pN.items():
dct[v].append(k)
# defaultdict(<class 'list'>, {10: ['dave', 'jacinta'], 8: ['james'], 6: ['john'], 3: ['jack'], 2: ['sam']})
Используйте sorted
для вывода:
for k, v in sorted(dct.items(), reverse=True):
print(k, ', '.join(v))
# Result
10 dave, jacinta
8 james
6 john
3 jack
2 sam
function
для возврата top n
пользователей (рассматривает связь как одну запись):
def top_n(d, n):
dct = defaultdict(list)
for k, v in d.items():
dct[v].append(k)
return sorted(dct.items())[-n:][::-1]
top_n(pN, 3)
# [(10, ['dave', 'jacinta']), (8, ['james']), (6, ['john'])]
Использование defaultdict
прост и быстр, и вот некоторые моменты, чтобы доказать это:
Функции, которые будут синхронизированы
def chris_z(d, n):
dct = defaultdict(list)
for k, v in d.items():
dct[v].append(k)
return sorted(dct.items())[-n:][::-1]
def tim_lombard(score_dict, n):
lot = [(k,v) for k, v in score_dict.items()] #make list of tuple from scores dict
nl = []
while len(lot)> 0:
nl.append(max(lot, key=lambda x: x[1]))
lot.remove(nl[-1])
def ajax(d, n:'n_users', top = True):
_ranks = sorted(d.values())
_ranks = _ranks[-n:] if top else _ranks[:n]
return {i:[a for a, b in d.items() if b == i] for i in _ranks}
Результаты
x = [''.join(i) for i in itertools.permutations('chrisz', 6)]
y = [random.randint(0, 100) for _ in range(720)]
z = dict(zip(x, y))
In [40]: %timeit chris_z(z, 500)
110 µs ± 259 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [42]: %timeit tim_lombard(z, 500)
26.2 ms ± 60 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
In [43]: %timeit ajax(z, 500)
15.3 ms ± 227 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Ответ 2
Вы можете использовать sorted
и понимание словаря:
from typing import Dict, List
def ranking(d, n:'n_users', top = True) -> Dict[int, List[str]]:
_ranks = sorted(d.values())
_ranks = _ranks[-n:] if top else _ranks[:n]
return {i:[a for a, b in d.items() if b == i] for i in _ranks}
pN ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
for a, b in sorted(ranking(pN, 10).items(), key=lambda x:x[0], reverse=True):
print('{} {}'.format(a, ', '.join(b)))
Выход:
10 dave, jacinta
8 james
6 john
3 jack
2 sam
Изменение: для любого числа самых популярных пользователей передайте значение функции:
_r = ranking(pN, 5) #for the top 5 users
Ответ 3
Будет ли это работать для вас?
pN ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
def top_n_scores(n, score_dict):
''' returns the n scores from a name:score dict'''
lot = [(k,v) for k, v in pN.items()] #make list of tuple from scores dict
nl = []
while len(lot)> 0:
nl.append(max(lot, key=lambda x: x[1]))
lot.remove(nl[-1])
return nl[0:n]
Чтобы получить лучшие 4 балла:
top_n_scores(4, pN)
[('dave', 10), ('jacinta', 10), ('james', 8), ('john', 6)]
Ответ 4
Вы должны попробовать его с помощью collections.defaultdict
с встроенной функцией sorted sorted()
.
from collections import defaultdict
def sort_it(_dict, n):
result = defaultdict(list)
for name, num in _dict.items():
result[num].append(name)
return sorted(result.items(), reverse=True)[:n]
>>> pN = {'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
>>> top3 = sort_it(pN, 3)
[(10, ['jacinta', 'dave']), (8, ['james']), (6, ['john'])] # Output
Ответ 5
Поскольку вы хотите группировать по баллам, было бы целесообразно использовать itertools.groupby
:
scores ={'dave': 10, 'jacinta': 10, 'james': 8, 'john': 6, 'jack': 3, 'sam': 2}
from itertools import groupby
from operator import itemgetter
get_score = itemgetter(1)
def group_users_by_score(scores, n=-1):
sorted_users = sorted(scores.items(), key=get_score, reverse=True)
top_n = sorted_users[:n]
return groupby(top_n, key=get_score)
def display_top_users(scores, n=-1):
for score, users in group_users_by_score(scores, n):
print("%3d %s" % (score, ', '.join(u for (u,s) in users)))
В качестве примера:
>>> display_top_users(scores, 3)
10 dave, jacinta
8 james
>>> display_top_users(scores)
10 dave, jacinta
8 james
6 john
3 jack