Отримайте ключ, що відповідає мінімальному значенню в словнику


304

Якщо у мене є словник Python, як мені отримати ключ до запису, який містить мінімальне значення?

Я думав про щось, що стосується min()функції ...

З огляду на вхід:

{320:1, 321:0, 322:3}

Це повернеться 321.


Друкувати у заяві про повернення? Інакше чому 321? Чи не повинно бути 320?
GreenMatt

3
@myself: Гаразд, тепер я бачу - те, що потрібно шукати, є ключем до запису, де значення запису мінімальне. Краще формулюйте питання, будь ласка, оскільки інші, очевидно, думали так само, як і я.
GreenMatt

2
День поінформованості щодо структури даних: якщо ви коли-небудь запитуєте (або видаляєте) мінімальний елемент, подумайте про використання черги з пріоритетом чи купі.
Полковник Паніка

Відповіді:


596

Найкраще: min(d, key=d.get)- немає причин вставляти марний lambdaшар непрямості або витягувати предмети чи ключі!


5
@ KarelBílek, це означає, що ви передали список "d", наприклад [11, 22, 33], замість словника, наприклад {1: 11, 2:22, 3:33}. 'd.get' дійсний для словника, але не для списку.
ToolmakerSteve

9
що робити, якщо два різні клавіші мають однакове значення? і вони бувають як найменшою цінністю? як ти можеш змусити його повернути обидва?
user3226932

5
Чи можна використовувати цю техніку, якщо значення dict є списками, наприклад:, d={"a":[10, None], "b":[20, None]}де min обчислюється від d [ключ] [0]?
TrakJohnson

4
Як це працює? Що таке функція min, я вважав, що min () взяв лише аргументи як окремі значення, так і списки. Як вона перебирає всі записи в словнику?
azureai

2
min()повернути значення в першому значенні в сортованому. ключ позначає спосіб сортування значень. key=d.getозначає, що список буде відсортований за значеннями словника.
notilas

45

Ось відповідь, яка насправді дає рішення, про яке попросила ОП:

>>> d = {320:1, 321:0, 322:3}
>>> d.items()
[(320, 1), (321, 0), (322, 3)]
>>> # find the minimum by comparing the second element of each tuple
>>> min(d.items(), key=lambda x: x[1]) 
(321, 0)

d.iteritems()Однак використання буде більш ефективним для більших словників.


3
Замість лямбда можна використовувати operator.itemgetter(1).
Філіпп

2
замість lamda використовуйте d.get
Texom512,

Це повертає не ключ за запитом, а пару (ключ, значення).
Ерік О Лебігот

14

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

d = {320:1, 321:0, 322:3, 323:0}

minval = min(d.values())
res = [k for k, v in d.items() if v==minval]

[321, 323]

Еквівалентна функціональна версія:

res = list(filter(lambda x: d[x]==minval, d))

1
Ваша відповідь дуже корисна, і інші, напевно, згодні: дивіться кілька коментарів до цього питання у прийнятій відповіді. Однак мені потрібно було повернутися двічі, щоб знайти його: чи могли б ви запропонувати змінити прийняту відповідь? Ваше насправді є доповненням.
jmon12



6

У випадку, коли у вас є кілька мінімальних ключів, і ви хочете, щоб це було просто

def minimums(some_dict):
    positions = [] # output variable
    min_value = float("inf")
    for k, v in some_dict.items():
        if v == min_value:
            positions.append(k)
        if v < min_value:
            min_value = v
            positions = [] # output variable
            positions.append(k)

    return positions

minimums({'a':1, 'b':2, 'c':-1, 'd':0, 'e':-1})

['e', 'c']

4

Якщо ви не впевнені, що у вас немає декількох мінімальних значень, я б запропонував:

d = {320:1, 321:0, 322:3, 323:0}
print ', '.join(str(key) for min_value in (min(d.values()),) for key in d if d[key]==min_value)

"""Output:
321, 323
"""

3

Редагувати: це відповідь на початкове запитання ОП щодо мінімального ключа, а не мінімальної відповіді.


Ви можете отримати ключі диктату за допомогою keysфункції, і ви маєте рацію використовувати minмінімум цього списку.


Насправді не заслуговує жодної позиції, оскільки оригінальне запитання плаката було не таким ясним, як це могло бути.
GreenMatt

@ Space_C0wb0y: можливо, ви можете бути настільки добрими, помітивши, що ОП редагувала його питання, щоб означати щось інше, після того, як я відповіла
Елі Бендерський,

3

Ще один підхід до вирішення проблеми декількох ключів з однаковим мінімальним значенням:

>>> dd = {320:1, 321:0, 322:3, 323:0}
>>>
>>> from itertools import groupby
>>> from operator import itemgetter
>>>
>>> print [v for k,v in groupby(sorted((v,k) for k,v in dd.iteritems()), key=itemgetter(0)).next()[1]]
[321, 323]

2

Використовуйте minз ітератором (для використання python 3 itemsзамість iteritems); замість лямбда використовувати itemgetterоператор від оператора, який швидше, ніж лямбда.

from operator import itemgetter
min_key, _ = min(d.iteritems(), key=itemgetter(1))


1

Я порівняв ефективність наступних трьох варіантів:

    import random, datetime

myDict = {}
for i in range( 10000000 ):
    myDict[ i ] = random.randint( 0, 10000000 )



# OPTION 1

start = datetime.datetime.now()

sorted = []
for i in myDict:
    sorted.append( ( i, myDict[ i ] ) )
sorted.sort( key = lambda x: x[1] )
print( sorted[0][0] )

end = datetime.datetime.now()
print( end - start )



# OPTION 2

start = datetime.datetime.now()

myDict_values = list( myDict.values() )
myDict_keys = list( myDict.keys() )
min_value = min( myDict_values )
print( myDict_keys[ myDict_values.index( min_value ) ] )

end = datetime.datetime.now()
print( end - start )



# OPTION 3

start = datetime.datetime.now()

print( min( myDict, key=myDict.get ) )

end = datetime.datetime.now()
print( end - start )

Вибірка зразка:

#option 1
236230
0:00:14.136808

#option 2
236230
0:00:00.458026

#option 3
236230
0:00:00.824048

0

щоб створити упорядкований клас, ви повинні перекрити 6 спеціальних функцій, щоб його викликали функцією min ()

ці методи є __lt__ , __le__, __gt__, __ge__, __eq__ , __ne__для того, щоб вони були меншими, меншими або рівними, більшими, більшими або рівними, рівними, не рівними. наприклад, вам слід реалізувати __lt__наступне:

def __lt__(self, other):
  return self.comparable_value < other.comparable_value

то ви можете використовувати функцію min наступним чином:

minValue = min(yourList, key=(lambda k: yourList[k]))

це працювало для мене.


0
min(zip(d.values(), d.keys()))[1]

Використовуйте функцію zip, щоб створити ітератор кортежів, що містять значення та ключі. Потім оберніть його функцією min, яка приймає мінімум на основі першої клавіші. Це повертає кортеж, що містить пару (значення, ключ). Індекс [1] використовується для отримання відповідного ключа


2
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як цей код відповідає на питання, покращує його довгострокове значення.
β.εηοιτ.βε

@ β.εηοιτ.βε що краще?
rajn

-1
# python 
d={320:1, 321:0, 322:3}
reduce(lambda x,y: x if d[x]<=d[y] else y, d.iterkeys())
  321

6
1) Зменшення, як правило, повільніше, ніж itertools. 2) Більшість реалізацій скорочення можна зробити простішими з будь-якими або всіма. 3) Я гігантський мундштук для GvR. 4) Операційний модуль робить більшість простих лямбдалей непотрібними, а складні лямбдати в будь-якому випадку слід визначати як реальні функції. Можливо, я просто боюся функціонального програмування. ;)
MikeD

@miked: розкажи більше. що таке gvr і що таке модуль оператора? Ви можете розмістити посилання? я, можливо, знаю інших, але я все ще просто посередник у python. готові вчитися! :-)
eruciform

Гвр - Гвідо ван Россум, доброзичливий диктатор Питона на все життя. Ось п’ятирічний допис від нього, в якому пояснюється, чому ліпсимам (карта, фільтр, зменшення, лямбда) не займає багато місця в пітоні, що рухається вперед, і ці причини досі вірні. Модуль оператора має заміни для вилучення членів : "lambda x: x [1]" порівняно з "itemgetter (1)" є символом довше, і, певно, потрібно більше часу для розуміння. Мені немає місця, але задайте питання!
MikeD

@miked: хочете спочатку вкусити яблуко? stackoverflow.com/questions/3292481/…
eruciform

Їх насправді немає потреби повторно реалізовувати щось вбудоване ( min()).
Ерік О Лебігот

-8

Це те, що ви шукаєте?

d = dict()
d[15.0]='fifteen'
d[14.0]='fourteen'
d[14.5]='fourteenandhalf'

print d[min(d.keys())]

Друкує «чотирнадцять»


8
-1: не те, що задали питання. Ви повертаєте значення з мінімальним ключем, ОП хоче ключ з мінімальним значенням
Брайан S
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.