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

Примере:

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

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

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

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

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

978
ricafeal 6 Ноя 2008 в 13:49

22 ответа

Лучший ответ

Вы можете использовать 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'
579
Priyanka Chaudhary 22 Фев 2018 в 17:51
max(stats, key=stats.get)
1087
A. Coady 11 Ноя 2008 в 06:24
Counter = 0
for word in stats.keys():
    if stats[word]> counter:
        Counter = stats [word]
print Counter
1
Corv Vette 26 Дек 2015 в 12:31

Для научных пользователей Python вот простое решение с использованием Pandas:

import pandas as pd
stats = {'a': 1000, 'b': 3000, 'c': 100}
series = pd.Series(stats)
series.idxmax()

>>> b
0
wkzhu 14 Фев 2020 в 04:00
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')
14
priya khokher 4 Май 2018 в 06:50

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

max(d, key = d.get) 
# which is equivalent to 
max(d, key = lambda k : d.get(k))

Для возврата ключа используйте пару значений:

max(d.items(), key = lambda k : k[1])
2
pk786 14 Фев 2020 в 17:22

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

4
Jasha 10 Янв 2018 в 05:32

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

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

28
Climbs_lika_Spyder 7 Авг 2018 в 18:16

Я не был удовлетворен ни одним из этих ответов. max всегда выбирает первый ключ с максимальным значением. Словарь может иметь несколько ключей с этим значением.

def keys_with_top_values(my_dict):
    return [key  for (key, value) in my_dict.items() if value == max(my_dict.values())]

Отправка этого ответа на случай, если он кому-то поможет. Смотрите ниже ТАК сообщение

Какой максимум выбирает Python в случае ничьей?

7
kslote1 19 Авг 2019 в 15:35

Вот еще один:

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

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

44
user994998 26 Янв 2014 в 22:09

По повторным решениям через комментарии в выбранном ответе ...

В Python 3:

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

В Python 2:

max(stats.iterkeys(), key=(lambda k: stats[k]))
10
watsonic 5 Май 2015 в 02:03

Я пришел сюда в поисках того, как вернуть 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']
10
donrondadon 12 Сен 2018 в 09:43

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

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

< Сильный > EDIT :

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

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

Ага...

Максимум

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

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

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

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

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

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

Dict

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

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

Закрытие

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

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

61
I159 21 Июл 2017 в 06:12

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

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

Вы можете получить коллекцию со всеми ключами с максимальным значением следующим образом:

from collections import defaultdict
from collections import OrderedDict

groupedByValue = defaultdict(list)
for key, value in sorted(stats.items()):
    groupedByValue[value].append(key)

# {1000: ['a'], 3000: ['b', 'd', 'e'], 100: ['c']}

groupedByValue[max(groupedByValue)]
# ['b', 'd', 'e']
0
Ignacio Alorre 14 Фев 2020 в 07:08
key, value = max(stats.iteritems(), key=lambda x:x[1])

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

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

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

39
Davoud Taghawi-Nejad 30 Сен 2015 в 18:39

Очередь кучи - это обобщенное решение, которое позволяет извлекать верхние 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, если ключ не найден, чего здесь не может быть.

5
jpp 1 Ноя 2018 в 11:05

Как насчет:

 max(zip(stats.keys(), stats.values()), key=lambda t : t[1])[0]
0
user2399453 4 Сен 2017 в 20:34

Я проверил принятый ответ и самое быстрое решение AND @ 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
0
ragardner 11 Июл 2017 в 16:26

+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])
2
blueseal 2 Янв 2018 в 08:57

Примере:

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

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

max(stats, key=stats.get)

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

56
leo022 23 Авг 2018 в 04:08

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

203
the wolf 22 Авг 2013 в 00:05

С 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. 
7
ukrutt 23 Фев 2016 в 18:58