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

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

пример:

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

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

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

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

Это лучший (или даже более элегантный) подход?

19 ответов


можно использовать operator.itemgetter для этого:

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

и вместо создания нового списка в памяти используйте stats.iteritems(). The до 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])

EDIT:

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

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

да...

Макс

max(iterable[, key])

max (arg1, arg2, *args[, key])

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

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

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

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

дикт

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

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

закрытие

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

The stats переменная доступна через на 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] в конце выражения. Мне никогда не нравилась читаемость лямбда-выражений, но это лучше, чем оператор.itemgetter (1) IMHO.


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

>>> 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"и любой другой максимальный ключ.

Примечание: для 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 is один из этих кортежей!--7-->. Итак, выбрав правильный индекс, вы выбираете, хотите ли вы сравнивать по ключам или по значениям.

Python 2

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

Примечания

  • этот ответ основан на комментариях Climbs_lika_spyder's answer.

  • используемый код был протестирован на Python 3.5.2 и Python 2.7.10 .


для итерационных решений через комментарии в выбранном ответе...

В Python 3:

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

В Python 2:

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

С collections.Counter вы могли бы сделать

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

при необходимости вы можете просто начать с пустого collections.Counter и добавить к нему

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

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

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

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

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')

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


+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])

пример:

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

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

max(stats, key=stats.get)

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


Я вот ищу как вернуть mydict.keys() исходя из стоимости mydict.values(). Вместо того, чтобы просто один ключ вернулся, я искал, чтобы вернуть top 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']

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

я протестировал принятый ответ и самое быстрое решение @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]