Получение ключа с максимальным значением в словаре? - PullRequest
706 голосов
/ 06 ноября 2008

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

Пример:

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

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

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

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

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

Ответы [ 20 ]

899 голосов
/ 11 ноября 2008
max(stats, key=stats.get)
508 голосов
/ 06 ноября 2008

Вы можете использовать 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'
186 голосов
/ 10 сентября 2012

Я протестировал МНОГИЕ варианты, и это самый быстрый способ вернуть ключ 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 в верхней части этого поста)

52 голосов
/ 07 февраля 2016

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

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

EDIT:

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

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

Угу ...

макс

макс (итерация [, ключ])

max (arg1, arg2, * args [, ключ])

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

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

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

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

Dict

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

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

Закрытие

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

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

36 голосов
/ 06 ноября 2008

Вот еще один:

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

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

33 голосов
/ 07 ноября 2008
key, value = max(stats.iteritems(), key=lambda x:x[1])

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

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

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

26 голосов
/ 23 августа 2018

Пример:

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

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

max(stats, key=stats.get)

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

22 голосов
/ 02 мая 2014

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

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

16 голосов
/ 17 декабря 2017

Чтобы получить максимальный ключ / значение словаря 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() для производительности.

Примечания

  • Этот ответ основан на комментариях к Ответ Climbs_lika_Spyder .

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

11 голосов
/ 04 мая 2018
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')
...