14

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

11

Я столкнулся с задачей, где у меня есть словарь, в котором ключи — это строки, а значения — целые числа. Вот пример словаря:

stats = {'a': 1, 'b': 3000, 'c': 0}

Мне нужно получить ключ с максимальным значением. В данном случае это будет 'b'.

Существует ли более элегантный способ решения этой задачи, чем использование промежуточного списка с перевернутыми кортежами ключ-значение?

Вот один из подходов, который я использую:

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

Однако хотелось бы узнать, есть ли более изящный или эффективный способ сделать это. Спасибо!

5 ответ(ов)

20

Чтобы получить элемент с максимальным значением из словаря stats, вы можете использовать функцию max() в Python, указывая аргумент key. Вот как это делается:

max(stats, key=stats.get)

Здесь stats.get используется в качестве функции, которая будет вызываться для каждого ключа в словаре stats. Функция max() в таком случае вернёт ключ, соответствующий максимальному значению. Если вам нужно получить саму пару ключ-значение, вы можете использовать max(stats.items(), key=lambda item: item[1]).

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

7

Вы можете использовать operator.itemgetter для этой задачи:

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

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

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

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

Если вы используете Python 3, то код будет таким же:

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

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

2

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

def keywithmaxval(d):
    """ a) создаем список ключей и значений словаря; 
        b) возвращаем ключ с максимальным значением """  
    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():
    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():
    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) создаем список ключей и значений словаря; 
        b) возвращаем ключ с максимальным значением """    
    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, ...}  # Полный словарь, как в вашем примере

И результаты тестирования под 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%
...

Как видно из тестов, f1, который представляет метод keywithmaxval, является самым быстрым вариантом как в Python 3.2, так и в Python 2.7.

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

1

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

max(d, key=d.get)

что эквивалентно следующему коду:

max(d, key=lambda k: d.get(k))

Чтобы вернуть пару ключ-значение, используйте:

max(d.items(), key=lambda k: k[1])
0

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

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

EDIT:

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

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

Конечно!

max

Функция max имеет следующие формы:

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

Она возвращает наибольший элемент в итерируемом объекте или наибольший из двух или более аргументов.

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

lambda <item>: <результат операции с item>

Сравниваются возвращенные значения.

Словарь

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

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

Замыкание

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

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь