Получаем ключ с максимальным значением в словаре?

StackOverflow https://stackoverflow.com/questions/268272

  •  06-07-2019
  •  | 
  •  

Вопрос

У меня есть dictionary:ключи - это строки, значения - целые числа.

Пример:

stats = {'a':1000, 'b':3000, 'c': 100}

Я бы хотел получить 'b' в качестве ответа, поскольку это ключ с более высоким значением.

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

inverse = [(value, key) for key, value in stats.items()]
print max(inverse)[1]

Является ли это одним из лучших (или даже более элегантных) подходов?

Это было полезно?

Решение

Для этого вы можете использовать operator.itemgetter :

import operator
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]

И вместо создания нового списка в памяти используйте stats.iteritems () . Параметр key для функции max () является функцией, которая вычисляет ключ, используемый для определения порядка ранжирования элементов.

Обратите внимание: если у вас будет другая пара ключ-значение 'd': 3000, этот метод вернет один из двух , даже если у них обоих есть максимальное значение.

>>> import operator
>>> stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000}
>>> max(stats.iteritems(), key=operator.itemgetter(1))[0]
'b' 

При использовании Python3:

>>> max(stats.items(), key=operator.itemgetter(1))[0]
'b'

Другие советы

max(stats, key=stats.get)

Я протестировал МНОГИЕ варианты, и это самый быстрый способ вернуть ключ dict с максимальным значением:

def keywithmaxval(d):
     """ a) create a list of the dict's keys and values; 
         b) return the key with the max value"""  
     v=list(d.values())
     k=list(d.keys())
     return k[v.index(max(v))]

Чтобы дать вам представление, вот несколько возможных методов:

def f1():  
     v=list(d1.values())
     k=list(d1.keys())
     return k[v.index(max(v))]

def f2():
    d3={v:k for k,v in d1.items()}
    return d3[max(d3)]

def f3():
    return list(filter(lambda t: t[1]==max(d1.values()), d1.items()))[0][0]    

def f3b():
    # same as f3 but remove the call to max from the lambda
    m=max(d1.values())
    return list(filter(lambda t: t[1]==m, d1.items()))[0][0]        

def f4():
    return [k for k,v in d1.items() if v==max(d1.values())][0]    

def f4b():
    # same as f4 but remove the max from the comprehension
    m=max(d1.values())
    return [k for k,v in d1.items() if v==m][0]        

def f5():
    return max(d1.items(), key=operator.itemgetter(1))[0]    

def f6():
    return max(d1,key=d1.get)     

def f7():
     """ a) create a list of the dict's keys and values; 
         b) return the key with the max value"""    
     v=list(d1.values())
     return list(d1.keys())[v.index(max(v))]    

def f8():
     return max(d1, key=lambda k: d1[k])     

tl=[f1,f2, f3b, f4b, f5, f6, f7, f8, f4,f3]     
cmpthese.cmpthese(tl,c=100) 

Тестовый словарь:

d1={1: 1, 2: 2, 3: 8, 4: 3, 5: 6, 6: 9, 7: 17, 8: 4, 9: 20, 10: 7, 11: 15, 
    12: 10, 13: 10, 14: 18, 15: 18, 16: 5, 17: 13, 18: 21, 19: 21, 20: 8, 
    21: 8, 22: 16, 23: 16, 24: 11, 25: 24, 26: 11, 27: 112, 28: 19, 29: 19, 
    30: 19, 3077: 36, 32: 6, 33: 27, 34: 14, 35: 14, 36: 22, 4102: 39, 38: 22, 
    39: 35, 40: 9, 41: 110, 42: 9, 43: 30, 44: 17, 45: 17, 46: 17, 47: 105, 48: 12, 
    49: 25, 50: 25, 51: 25, 52: 12, 53: 12, 54: 113, 1079: 50, 56: 20, 57: 33, 
    58: 20, 59: 33, 60: 20, 61: 20, 62: 108, 63: 108, 64: 7, 65: 28, 66: 28, 67: 28, 
    68: 15, 69: 15, 70: 15, 71: 103, 72: 23, 73: 116, 74: 23, 75: 15, 76: 23, 77: 23, 
    78: 36, 79: 36, 80: 10, 81: 23, 82: 111, 83: 111, 84: 10, 85: 10, 86: 31, 87: 31, 
    88: 18, 89: 31, 90: 18, 91: 93, 92: 18, 93: 18, 94: 106, 95: 106, 96: 13, 9232: 35, 
    98: 26, 99: 26, 100: 26, 101: 26, 103: 88, 104: 13, 106: 13, 107: 101, 1132: 63, 
    2158: 51, 112: 21, 113: 13, 116: 21, 118: 34, 119: 34, 7288: 45, 121: 96, 122: 21, 
    124: 109, 125: 109, 128: 8, 1154: 32, 131: 29, 134: 29, 136: 16, 137: 91, 140: 16, 
    142: 104, 143: 104, 146: 117, 148: 24, 149: 24, 152: 24, 154: 24, 155: 86, 160: 11, 
    161: 99, 1186: 76, 3238: 49, 167: 68, 170: 11, 172: 32, 175: 81, 178: 32, 179: 32, 
    182: 94, 184: 19, 31: 107, 188: 107, 190: 107, 196: 27, 197: 27, 202: 27, 206: 89, 
    208: 14, 214: 102, 215: 102, 220: 115, 37: 22, 224: 22, 226: 14, 232: 22, 233: 84, 
    238: 35, 242: 97, 244: 22, 250: 110, 251: 66, 1276: 58, 256: 9, 2308: 33, 262: 30, 
    263: 79, 268: 30, 269: 30, 274: 92, 1300: 27, 280: 17, 283: 61, 286: 105, 292: 118, 
    296: 25, 298: 25, 304: 25, 310: 87, 1336: 71, 319: 56, 322: 100, 323: 100, 325: 25, 
    55: 113, 334: 69, 340: 12, 1367: 40, 350: 82, 358: 33, 364: 95, 376: 108, 
    377: 64, 2429: 46, 394: 28, 395: 77, 404: 28, 412: 90, 1438: 53, 425: 59, 430: 103, 
    1456: 97, 433: 28, 445: 72, 448: 23, 466: 85, 479: 54, 484: 98, 485: 98, 488: 23, 
    6154: 37, 502: 67, 4616: 34, 526: 80, 538: 31, 566: 62, 3644: 44, 577: 31, 97: 119, 
    592: 26, 593: 75, 1619: 48, 638: 57, 646: 101, 650: 26, 110: 114, 668: 70, 2734: 41, 
    700: 83, 1732: 30, 719: 52, 728: 96, 754: 65, 1780: 74, 4858: 47, 130: 29, 790: 78, 
    1822: 43, 2051: 38, 808: 29, 850: 60, 866: 29, 890: 73, 911: 42, 958: 55, 970: 99, 
    976: 24, 166: 112}

И результаты теста под Python 3.2:

    rate/sec       f4      f3    f3b     f8     f5     f2    f4b     f6     f7     f1
f4       454       --   -2.5% -96.9% -97.5% -98.6% -98.6% -98.7% -98.7% -98.9% -99.0%
f3       466     2.6%      -- -96.8% -97.4% -98.6% -98.6% -98.6% -98.7% -98.9% -99.0%
f3b   14,715  3138.9% 3057.4%     -- -18.6% -55.5% -56.0% -56.4% -58.3% -63.8% -68.4%
f8    18,070  3877.3% 3777.3%  22.8%     -- -45.4% -45.9% -46.5% -48.8% -55.5% -61.2%
f5    33,091  7183.7% 7000.5% 124.9%  83.1%     --  -1.0%  -2.0%  -6.3% -18.6% -29.0%
f2    33,423  7256.8% 7071.8% 127.1%  85.0%   1.0%     --  -1.0%  -5.3% -17.7% -28.3%
f4b   33,762  7331.4% 7144.6% 129.4%  86.8%   2.0%   1.0%     --  -4.4% -16.9% -27.5%
f6    35,300  7669.8% 7474.4% 139.9%  95.4%   6.7%   5.6%   4.6%     -- -13.1% -24.2%
f7    40,631  8843.2% 8618.3% 176.1% 124.9%  22.8%  21.6%  20.3%  15.1%     -- -12.8%
f1    46,598 10156.7% 9898.8% 216.7% 157.9%  40.8%  39.4%  38.0%  32.0%  14.7%     --

И под Python 2.7:

    rate/sec       f3       f4     f8    f3b     f6     f5     f2    f4b     f7     f1
f3       384       --    -2.6% -97.1% -97.2% -97.9% -97.9% -98.0% -98.2% -98.5% -99.2%
f4       394     2.6%       -- -97.0% -97.2% -97.8% -97.9% -98.0% -98.1% -98.5% -99.1%
f8    13,079  3303.3%  3216.1%     --  -5.6% -28.6% -29.9% -32.8% -38.3% -49.7% -71.2%
f3b   13,852  3504.5%  3412.1%   5.9%     -- -24.4% -25.8% -28.9% -34.6% -46.7% -69.5%
f6    18,325  4668.4%  4546.2%  40.1%  32.3%     --  -1.8%  -5.9% -13.5% -29.5% -59.6%
f5    18,664  4756.5%  4632.0%  42.7%  34.7%   1.8%     --  -4.1% -11.9% -28.2% -58.8%
f2    19,470  4966.4%  4836.5%  48.9%  40.6%   6.2%   4.3%     --  -8.1% -25.1% -57.1%
f4b   21,187  5413.0%  5271.7%  62.0%  52.9%  15.6%  13.5%   8.8%     -- -18.5% -53.3%
f7    26,002  6665.8%  6492.4%  98.8%  87.7%  41.9%  39.3%  33.5%  22.7%     -- -42.7%
f1    45,354 11701.5% 11399.0% 246.8% 227.4% 147.5% 143.0% 132.9% 114.1%  74.4%     -- 

Вы можете видеть, что f1 является самым быстрым в Python 3.2 и 2.7 (или, точнее, keywithmaxval в верхней части этого поста)

Если вам нужно знать только ключ с максимальным значением, вы можете сделать это без него iterkeys или iteritems потому что итерация по словарю в Python - это итерация по его ключам.

max_key = max(stats, key=lambda k: stats[k])

Редактировать:

Из комментариев, @user1274878 :

Я новичок в python.Не могли бы вы, пожалуйста, поэтапно объяснить свой ответ?

Ага...

макс.

макс (повторяемый[, ключ])

макс (arg1, arg2, *args[, ключ])

Возвращает самый большой элемент в итерации или самый большой из двух или более аргументов.

Необязательный key аргумент описывает, как сравнивать элементы, чтобы получить максимум среди них:

lambda <item>: return <a result of operation with item> 

Возвращенные значения будут сравнены.

Диктовать

Python dict - это хэш-таблица.Ключ dict - это хэш объекта, объявленного как ключ.Из-за соображений производительности итерация выполняется через dict, реализованный как итерация через его ключи.

Поэтому мы можем использовать его, чтобы избавить операцию от получения списка ключей.

Закрытие

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

Тот Самый stats переменная, доступная через __closure__ атрибут lambda функционирует как указатель на значение переменной, определенной в родительской области.

Вот еще один:

stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iterkeys(), key=lambda k: stats[k])

Функция key просто возвращает значение, которое следует использовать для ранжирования, а max () сразу же возвращает требуемый элемент.

key, value = max(stats.iteritems(), key=lambda x:x[1])

Если вас не волнует ценность (я бы удивился, но), вы можете сделать следующее:

key, _ = max(stats.iteritems(), key=lambda x:x[1])

Мне нравится распаковка кортежей лучше, чем индекс [0] в конце выражения. Мне никогда не нравилась читабельность лямбда-выражений, но я считаю, что это лучше, чем operator.itemgetter (1) IMHO.

Пример:

stats = {'a':1000, 'b':3000, 'c': 100}

если вы хотите найти максимальное значение с помощью его ключа, возможно, отслеживание могло бы быть простым, без каких-либо соответствующих функций.

max(stats, key=stats.get)

выходной сигнал - это ключ, который имеет максимальное значение.

Учитывая, что более одной записи могут иметь максимальное значение. Я бы составил список ключей, которые имеют максимальное значение в качестве значения.

>>> stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000}
>>> [key for m in [max(stats.values())] for key,val in stats.iteritems() if val == m]
['b', 'd']

Это даст вам 'b' и любой другой ключ max.

Примечание: для Python 3 используйте stats.items () вместо stats.iteritems ()

Чтобы получить максимальный ключ / значение из словаря stats:

stats = {'a':1000, 'b':3000, 'c': 100}
  • Основанный на ключи

>>> max(stats.items(), key = lambda x: x[0]) ('c', 100)

  • Основанный на ценности

>>> max(stats.items(), key = lambda x: x[1]) ('b', 3000)

Конечно, если вы хотите получить только ключ или значение из результата, вы можете использовать индексацию кортежей.Например, чтобы получить ключ, соответствующий максимальному значению:

>>> max(stats.items(), key = lambda x: x[1])[0] 'b'

Объяснение

Словарный метод items() в Python 3 возвращает просмотр объекта из словаря.Когда этот объект представления повторяется, с помощью max функция, она выдает элементы словаря в виде кортежей вида (key, value).

>>> list(stats.items()) [('c', 100), ('b', 3000), ('a', 1000)]

Когда вы используете lambda выражение lambda x: x[1], на каждой итерации, x является одним из таких кортежей (key, value).Итак, выбирая правильный индекс, вы выбираете, хотите ли вы сравнивать по ключам или по значениям.

Python 2

Для версий Python 2.2+ будет работать тот же код.Однако лучше использовать iteritems() словарный метод вместо items() для повышения производительности.

Примечания

d = {'A': 4,'B':10}

min_v = min(zip(d.values(), d.keys()))
# min_v is (4,'A')

max_v = max(zip(d.values(), d.keys()))
# max_v is (10,'B')

Для повторных решений с помощью комментариев в выбранном ответе ...

В Python 3:

max(stats.keys(), key=(lambda k: stats[k]))

В Python 2:

max(stats.iterkeys(), key=(lambda k: stats[k]))

С collection.Counter вы можете сделать

>>> import collections
>>> stats = {'a':1000, 'b':3000, 'c': 100}
>>> stats = collections.Counter(stats)
>>> stats.most_common(1)
[('b', 3000)]

Если это уместно, вы можете просто начать с пустого collection.Counter и добавить к нему

>>> stats = collections.Counter()
>>> stats['a'] += 1
:
etc. 

Я добрался сюда в поисках того, как вернуться mydict.keys() основываясь на значении mydict.values().Вместо того, чтобы возвращать только один ключ, я хотел вернуть верхний x количество значений.

Это решение проще, чем использование max() функция, и вы можете легко изменить количество возвращаемых значений:

stats = {'a':1000, 'b':3000, 'c': 100}

x = sorted(stats, key=(lambda key:stats[key]), reverse=True)
['b', 'a', 'c']

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

x[0]
['b']

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

x[:2]
['b', 'a']

Спасибо, очень элегантно, я не помню, чтобы max разрешил " ключ " Параметр.

Кстати, чтобы получить правильный ответ ('b'), он должен быть:

import operator
stats = {'a':1000, 'b':3000, 'c': 100}
max(stats.iteritems(), key=operator.itemgetter(1))[0]

max ((значение, ключ) для ключа, значение в stats.items ()) [1]

Counter = 0
for word in stats.keys():
    if stats[word]> counter:
        Counter = stats [word]
print Counter

+1 к простейшей версии @Aric Coady решение.
А также один из способов случайного выбора одного из ключей с максимальным значением в словаре:

stats = {'a':1000, 'b':3000, 'c': 100, 'd':3000}

import random
maxV = max(stats.values())
# Choice is one of the keys with max value
choice = random.choice([key for key, value in stats.items() if value == maxV])

Очередь кучи - это обобщенное решение, которое позволяет извлекать верхние n ключи, упорядоченные по значению:

from heapq import nlargest

stats = {'a':1000, 'b':3000, 'c': 100}

res1 = nlargest(1, stats, key=stats.__getitem__)  # ['b']
res2 = nlargest(2, stats, key=stats.__getitem__)  # ['b', 'a']

res1_val = next(iter(res1))                       # 'b'

Примечание dict .__ getitem __ - это метод, вызываемый синтаксическим сахаром dict [] . В отличие от dict.get , он вернет KeyError , если ключ не найден, чего здесь не может быть.

Я протестировал принятый ответ И самое быстрое решение @thewolf на очень простом цикле, и цикл был быстрее, чем оба:

import time
import operator


d = {"a"+str(i): i for i in range(1000000)}

def t1(dct):
    mx = float("-inf")
    key = None
    for k,v in dct.items():
        if v > mx:
            mx = v
            key = k
    return key

def t2(dct):
    v=list(dct.values())
    k=list(dct.keys())
    return k[v.index(max(v))]

def t3(dct):
    return max(dct.items(),key=operator.itemgetter(1))[0]

start = time.time()
for i in range(25):
    m = t1(d)
end = time.time()
print ("Iterating: "+str(end-start))

start = time.time()
for i in range(25):
    m = t2(d)
end = time.time()
print ("List creating: "+str(end-start))

start = time.time()
for i in range(25):
    m = t3(d)
end = time.time()
print ("Accepted answer: "+str(end-start))

Результаты:

Iterating: 3.8201940059661865
List creating: 6.928712844848633
Accepted answer: 5.464320182800293

Как насчет

 max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top