Bir sözlük içindeki minimum değere karşılık gelen anahtarı alın


305

Bir Python sözlüğüm varsa, minimum değeri içeren girişin anahtarını nasıl alabilirim?

Bu min()işlevle ilgili bir şeyler düşünüyordum ...

Girdi verildiğinde:

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

Dönecekti 321.


Yazdığınız beyannamede? Aksi halde, neden 321? 320 değil mi?
GreenMatt

3
@ myself: Tamam, şimdi anlıyorum - istenen şey, girişin değerinin minimum olduğu girişin anahtarıdır. Sorunun daha iyi ifade edilmesi lütfen, diğerleri açıkça benim yaptığım gibi düşündü.
GreenMatt

2
Veri yapısı farkındalık günü: Yalnızca minimum öğeyi sorgularsanız (veya kaldırırsanız), bir öncelik kuyruğu veya yığını kullanmayı düşünün.
Albay Panik

Yanıtlar:


597

En iyi: min(d, key=d.get)- yararsız bir lambdadolaylama katmanı araya veya öğeleri veya anahtarları ayıklamak için bir sebep yok !


5
@ KarelBílek demek [11, 22, 33]bir sözlük yerine, örneğin bir liste "d" olarak geçti anlamına gelir {1: 11, 2:22, 3:33}. 'd.get' sözlük için geçerlidir, ancak liste için geçerli değildir.
ToolmakerSteve

9
iki farklı anahtar aynı değere sahipse ne olur? ve her ikisi de en küçük değer olur mu? ikisini de nasıl geri getirebilirsin?
user3226932

5
Bu teknik, dict değerleri listeler ise kullanılabilir, örn: d={"a":[10, None], "b":[20, None]}min, d [key] [0] 'dan hesaplanır mı?
TrakJohnson

4
Bu nasıl çalışıyor? Min işlevi ne tür olduğunu düşünüyorum, min () sadece bağımsız değerleri veya listeleri bağımsız değişken olarak aldı düşündüm. Sözlükteki tüm girişler üzerinde nasıl döngü oluşturur?
azureai

2
min()ilk değerdeki değeri sıralanmış olarak döndürür. tuşu, değerleri sıralamanın yolunu belirler. key=d.getlistenin sözlüğün değerlerine göre sıralanacağı anlamına gelir.
notilas

45

İşte OP'nin istediği çözümü veren bir cevap:

>>> 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()Bununla birlikte, daha büyük sözlükler için kullanmak daha verimli olacaktır.


3
Lambda yerine kullanabilirsiniz operator.itemgetter(1).
Philipp

2
bunun yerine lamda d.get kullanın
Texom512 12:15

Bu, anahtarı istendiği gibi döndürmez, ancak (anahtar, değer) çiftini döndürür.
Eric O Lebigot

14

Eşit en düşük değere sahip birden fazla anahtar için bir liste kavrama kullanabilirsiniz:

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]

Eşdeğer bir işlevsel versiyon:

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

1
Cevabınız çok faydalı ve diğerleri de aynı fikirde: kabul edilen cevapta bu konuyla ilgili birden fazla yoruma bakın. Ancak, onu bulmak için iki kez geri gelmem gerekiyordu: Kabul edilen cevaba bir düzenleme önermeyi düşünür müsünüz? Seninki aslında tamamlayıcı.
jmon12


6
>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321

@SilentGhost, @ blob8108: D'oh! Snafu kopyala ve yapıştır. Şimdi düzeltildi.
Daniel Stutzbach

Güzel çözüm bence, ama anonim fonksiyonu sadece bir dolaylama katmanı ekler: key=d.getdaha iyidir.
Eric O Lebigot

6

Birden çok minimal anahtarınız olduğu ve basit tutmak istediğiniz durumda

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

Birden fazla minimum değeriniz olmadığından emin değilseniz şunları öneririm:

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

Düzenleme: Bu OP'nin asgari anahtarla ilgili asıl sorunun cevabıdır, minimal cevap değildir.


Bu keysişlevi kullanarak diktenin anahtarlarını alabilirsiniz ve minbu listenin minimumunu bulmak için kullanmakta haklısınız .


Posterin orijinal sorusu olabildiğince açık olmadığı için gerçekten bir aşağı oyu hak etmiyor.
GreenMatt

@ Space_C0wb0y: belki de OP'nin sorusunu cevapladıktan sonra farklı bir anlama gelmesi için düzenlediğini fark etmek çok nazik olabilirsiniz
Eli Bendersky

3

Aynı min değerine sahip birden çok anahtar sorununu ele almak için başka bir yaklaşım:

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

minBir yineleyici ile kullanın ( itemsyerine python 3 kullanımı için iteritems); lambda yerine lambda'dan itemgetterdaha hızlı olan operatörden kullanın .

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

1
d={}
d[320]=1
d[321]=0
d[322]=3
value = min(d.values())
for k in d.keys(): 
    if d[k] == value:
        print k,d[k]

Sıfırın ÜZERİNDEKİ en küçük değeri nasıl çözeceğiniz hakkında bir fikriniz var mı?
Kaptan Anonim

1

Aşağıdaki üç seçeneğin nasıl performans gösterdiğini karşılaştırdım:

    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 )

Örnek çıktı:

#option 1
236230
0:00:14.136808

#option 2
236230
0:00:00.458026

#option 3
236230
0:00:00.824048

0

düzenlenebilir bir sınıf oluşturmak için min () işlevi tarafından çağrılacak şekilde 6 özel işlevi geçersiz kılmanız gerekir

bu yöntemler sırasıyla __lt__ , __le__, __gt__, __ge__, __eq__ , __ne__küçük, eşit ya da eşit, büyük, eşit ya da eşit, eşit, eşit değildir. örneğin __lt__aşağıdaki gibi uygulama yapmalısınız :

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

min işlevini aşağıdaki gibi kullanabilirsiniz:

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

bu benim için çalıştı.


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

Değerler ve anahtarlar içeren bir tuples yinelemesi oluşturmak için zip işlevini kullanın. Ardından, ilk tuşa dayanarak minimum değeri alan bir min işleviyle sarın. Bu, (değer, anahtar) çifti içeren bir demet döndürür. [1] dizini ilgili anahtarı almak için kullanılır


2
Bu kod soruyu cevaplayabilirken, bu kodun soruyu neden ve / veya nasıl cevapladığı konusunda ek bağlam sağlamak uzun vadeli değerini arttırır.
βε.εηοιτ.βε

@ β.εηοιτ.βε daha iyi mi?
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) Azaltma genellikle itertools'tan daha yavaştır. 2) Azaltma uygulamalarının çoğu, herhangi biri veya tümü ile daha basit yapılabilir. 3) Ben GvR için dev bir ağızlık duyuyorum. 4) Operatör modülü en basit lambdaları gereksiz kılar ve karmaşık lambdalar yine de gerçek işlevler olarak tanımlanmalıdır. Belki de sadece fonksiyonel programlamadan korkuyorum. ;)
MikeD

@miked: daha fazlasını anlat. gvr nedir ve operatör modülü nedir? link gönderebilir misiniz? Ben başkalarını tanıyabilir, ama ben hala sadece python bir arabulucuyum. öğrenmeye istekli! :-)
eruciform

GvR, Python'un yaşam için hayırsever diktatörü Guido van Rossum'dur. İşte ondan lisp-izm'lerin (harita, filtre, azaltma, lambda) neden python'da neden fazla yeri olmadığını açıklayan beş yaşındaki bir yazı ve bugün bu nedenler hala geçerli. Operatör modülünde üyelerin çıkarılması için yedek parçalar bulunur : "itemgetter (1)" ile karşılaştırıldığında "lambda x: x [1]" daha uzun bir karakterdir ve anlaşılması daha uzun sürer. Boş alanım yok, ama soru sor!
MikeD

@miked: ilk elma ısırmak ister misin? stackoverflow.com/questions/3292481/…
eruciform

Onların ( min()) yerleşik bir şeyi yeniden uygulamaya gerek yoktur .
Eric O Lebigot

-8

Aradığınız bu mu?

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

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

'On dört' yazdırır


8
-1: sorunun sorduğu şey değil. Değeri minimum anahtarla döndürüyorsunuz, OP minimum değere sahip anahtar istiyor
Brian S
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.