Возврат трех максимальных значений в словаре - PullRequest
0 голосов
/ 20 ноября 2018

У меня есть следующий словарь:

'{0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49, 9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408, 16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}'

И для этого словаря я хочу написать функцию, которая возвращает три пары ключ-значение, которые имеют самые высокие значения (поэтому в этомcase case 18, 19, 20).

Я придумал следующее:

cachedict = nr_of_objects_per_century() #Dictionary mentioned above

def top_3_centuries():
        max_nr_works_list = sorted(cachedict.values())
        top_3_values = []
        for i in range(len(max_nr_works_list)-3, len(max_nr_works_list)):
            top_3_values.append(max_nr_works_list[i])
            print(top_3_values)

Это дает мне список максимальных значений, которые я хочу найти.Но как мне продолжить отсюда?Есть ли способ сделать это без обратного просмотра (что медленно для словарей, верно?) У меня есть ощущение, что я могу выполнить эту задачу гораздо более эффективно / питонически.

Ответы [ 8 ]

0 голосов
/ 20 ноября 2018

Возвращает то, что вы хотите:

d = {0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49, 9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408, 16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}

print(sorted([(i,j) for i, j in d.items() if j in (sorted(d.values())[-3:])])[-3:])
#[(18, 111490), (19, 244675), (20, 115878)]
0 голосов
/ 20 ноября 2018

в два простых шага:

aux = sorted([(v,k) for (k,v) in dic.items()])
res = [(v,k) for (k,v) in aux[-3:]] 
#[(18, 111490), (20, 115878), (19, 244675)]

быстрее, чем nlargest и Counter.most_common в этом примере.

0 голосов
/ 20 ноября 2018

Вы ищете наиболее эффективный или просто оптимальный способ простоты permormace / алгоритма?

Если это последнее, возможно, вам следует рассмотреть сортировку элементов словаря как кортежей (вы можете получить их с помощью cachedict.items ()) как в этом ответе https://stackoverflow.com/a/613218/10453363

Просто отсортируйте кортежи по значению, а затем получите последние 3 кортежа (которые являются парами ключ / значение)

0 голосов
/ 20 ноября 2018

Вы можете использовать это:

a = {0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49,
       9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408,
       16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}

l = sorted(list(a.items()), key=lambda tup: tup[1], reverse=True)[:3]
print(l) # [(19, 244675), (20, 115878), (18, 111490)]

Преобразует словарь a в список кортежей, сортирует по tup[1], переворачивает его и получает первые 3 попадания.

0 голосов
/ 20 ноября 2018

heapq.nlargest

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

from heapq import nlargest
from operator import itemgetter

dct = {0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49,
       9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408,
       16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}

res = nlargest(3, dct.items(), key=itemgetter(1))

print(res)
# [(19, 244675), (20, 115878), (18, 111490)]
0 голосов
/ 20 ноября 2018

Вы можете сделать это так:

dct = {0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49, 9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408, 16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}

res = [next(k for k in dct if dct[k]==v) for v in sorted(dct.values(), reverse=True)[:3]]
print(res)  # -> [19, 20, 18]

Разбивка:

  • sorted(dct.values(), reverse=True)[:3] :: Принимает 3 максимальных значения словаря.
  • next(k for k in dct if dct[k]==v) :: возвращает ключ словаря, для которого значение является одним из вышеуказанных 3 (итеративно).
0 голосов
/ 20 ноября 2018

Вы также можете использовать collections.Counter с most_common (который внутренне использует очередь кучи):

from collections import Counter

dct = {0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49, 
       9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408, 
       16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}

count = Counter(dct)
print(count.most_common(3))  # [(19, 244675), (20, 115878), (18, 111490)]
0 голосов
/ 20 ноября 2018
d = {0: 0, 1: 11, 2: 26, 3: 43, 4: 14, 5: 29, 6: 34, 7: 49, 8: 49, 9: 108, 10: 124, 11: 108, 12: 361, 13: 290, 14: 2118, 15: 5408, 16: 43473, 17: 109462, 18: 111490, 19: 244675, 20: 115878, 21: 6960}

d_items_sorted = sorted(d.items(), key=lambda x: x[1], reverse=True)

d_items_sorted[:3]

Возвращает:

[(19, 244675), (20, 115878), (18, 111490)]

Это самый простой код, который я мог получить, но сортировка словаря стоит O (nlogn), и вы должны быть в состоянии сделать то же самое в O (n)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...