Получение ключа с максимальным значением в словаре?
у меня есть 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'
я протестировал много вариантов, и это самый быстрый способ вернуть ключ 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')
+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']
я протестировал принятый ответ и самое быстрое решение @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