Dapatkan kunci yang sesuai dengan nilai minimum dalam kamus

305

Jika saya memiliki kamus Python, bagaimana cara mendapatkan kunci entri yang berisi nilai minimum?

Saya sedang memikirkan sesuatu untuk dilakukan dengan min()fungsi ...

Diberikan input:

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

Itu akan kembali 321.

tjvr
sumber
Mengetik dalam pengembalian yang dinyatakan? Kalau tidak, mengapa 321? Bukankah seharusnya 320?
GreenMatt
3
@myself: Oke, sekarang saya mengerti - apa yang diinginkan adalah kunci untuk entri di mana nilai entri adalah minimum. Lebih baik kata-kata untuk pertanyaan itu, karena orang lain jelas berpikir sama seperti saya.
GreenMatt
2
Hari kesadaran struktur data: jika Anda hanya meminta (atau menghapus) elemen minimum, pertimbangkan untuk menggunakan antrian atau tumpukan prioritas.
Kolonel Panic

Jawaban:

597

Terbaik: min(d, key=d.get)- tidak ada alasan untuk menempatkan lambdalapisan tipuan yang tidak berguna atau mengekstrak item atau kunci!

Alex Martelli
sumber
5
@ KarelBílek artinya Anda memasukkan sebagai "d" daftar misalnya [11, 22, 33], bukan kamus misalnya {1: 11, 2:22, 3:33}. 'd.get' valid untuk kamus, tetapi tidak untuk daftar.
ToolmakerSteve
9
bagaimana jika dua kunci berbeda memiliki nilai yang sama? dan mereka berdua menjadi nilai terkecil? bagaimana Anda bisa mengembalikan keduanya?
user3226932
5
Bisakah teknik ini digunakan jika nilai dict adalah daftar, misalnya:, di d={"a":[10, None], "b":[20, None]}mana min dihitung dari d [kunci] [0]?
TrakJohnson
4
Bagaimana cara kerjanya? Seperti apa fungsi min itu, saya pikir min () hanya mengambil nilai individual atau daftar sebagai argumen. Bagaimana cara mengulang semua entri dalam kamus?
azureai
2
min()kembalikan nilai pada nilai pertama diurutkan. kunci menentukan cara untuk mengurutkan nilai. key=d.getberarti daftar akan diurutkan berdasarkan nilai kamus.
notilas
45

Inilah jawaban yang benar-benar memberikan solusi yang diminta OP:

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

Namun, penggunaan d.iteritems()akan lebih efisien untuk kamus yang lebih besar.

Mark Rushakoff
sumber
3
Alih-alih lambda yang bisa Anda gunakan operator.itemgetter(1).
Philipp
2
bukannya lamda gunakan d.get
Texom512
Ini tidak mengembalikan kunci seperti yang diminta, tetapi pasangan (kunci, nilai).
Eric O Lebigot
14

Untuk beberapa kunci yang memiliki nilai terendah yang sama, Anda dapat menggunakan pemahaman daftar:

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]

Versi fungsional yang setara:

res = list(filter(lambda x: d[x]==minval, d))
jpp
sumber
1
Jawaban Anda sangat berguna dan orang lain mungkin setuju: lihat beberapa komentar untuk hal itu dalam jawaban yang diterima. Namun, saya perlu kembali dua kali untuk menemukannya: apakah Anda akan mempertimbangkan untuk mengusulkan edit pada jawaban yang diterima? Milikmu sebenarnya saling melengkapi.
jmon12
11

min(d.items(), key=lambda x: x[1])[0]

abyx
sumber
6
>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321
Daniel Stutzbach
sumber
@ SilentGhost, @ blob8108: D'oh! Salin dan tempel snafu. Diperbaiki sekarang
Daniel Stutzbach
Solusi yang baik saya pikir, tetapi fungsi anonim hanya menambahkan lapisan tipuan: key=d.getlebih baik.
Eric O Lebigot
6

Untuk kasus di mana Anda memiliki beberapa kunci minimal dan ingin membuatnya tetap sederhana

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']
netskink
sumber
4

Jika Anda tidak yakin bahwa Anda tidak memiliki beberapa nilai minimum, saya sarankan:

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
"""
Tony Veijalainen
sumber
3

Sunting: ini adalah jawaban untuk pertanyaan awal OP tentang kunci minimal, bukan jawaban minimal.


Anda bisa mendapatkan kunci dikt menggunakan keysfungsi, dan Anda benar tentang menggunakan minuntuk menemukan minimum daftar itu.

Eli Bendersky
sumber
Tidak benar-benar layak mendapatkan downvote, karena pertanyaan asli poster itu tidak sejelas mungkin.
GreenMatt
@ Space_C0wb0y: mungkin Anda bisa berbaik hati memperhatikan bahwa OP mengedit pertanyaannya untuk mengartikan sesuatu yang berbeda, setelah saya menjawab
Eli Bendersky
3

Pendekatan lain untuk mengatasi masalah beberapa kunci dengan nilai min yang sama:

>>> 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]
PaulMcG
sumber
2

Gunakan mindengan iterator (untuk penggunaan python 3 itemsbukan iteritems); bukannya lambda gunakan itemgetterdari operator, yang lebih cepat dari lambda.

from operator import itemgetter
min_key, _ = min(d.iteritems(), key=itemgetter(1))
Antti Haapala
sumber
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]
aditya royal matturi
sumber
Adakah yang tahu bagaimana menghitung nilai terkecil DI ATAS nol?
Kapten Anonim
1

Saya membandingkan kinerja tiga opsi berikut:

    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 )

Output sampel:

#option 1
236230
0:00:14.136808

#option 2
236230
0:00:00.458026

#option 3
236230
0:00:00.824048
svinec
sumber
0

untuk membuat kelas yang dapat dipesan, Anda harus mengganti 6 fungsi khusus, sehingga akan dipanggil oleh fungsi min ()

metode-metode ini __lt__ , __le__, __gt__, __ge__, __eq__ , __ne__agar mereka kurang dari, kurang dari atau sama, lebih besar dari, lebih besar dari atau sama, sama, tidak sama. misalnya Anda harus menerapkan __lt__sebagai berikut:

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

maka Anda dapat menggunakan fungsi min sebagai berikut:

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

ini berhasil untuk saya.

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

Gunakan fungsi zip untuk membuat iterator tuple yang berisi nilai dan kunci. Kemudian bungkus dengan fungsi min yang mengambil minimum berdasarkan kunci pertama. Ini mengembalikan tuple yang berisi pasangan (nilai, kunci). Indeks [1] digunakan untuk mendapatkan kunci yang sesuai

rajn
sumber
2
Sementara kode ini dapat menjawab pertanyaan, memberikan konteks tambahan tentang mengapa dan / atau bagaimana kode ini menjawab pertanyaan meningkatkan nilai jangka panjangnya.
β.εηοιτ.βε
@ β.εηοιτ.βε lebih baik?
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
eruciform
sumber
6
1) Mengurangi umumnya lebih lambat dari itertools. 2) Sebagian besar implementasi pengurangan dapat dilakukan lebih sederhana dengan apa pun atau semua. 3) Saya adalah juru bicara raksasa untuk GvR. 4) Modul operator membuat lambda paling sederhana tidak perlu, dan lambda kompleks harus didefinisikan sebagai fungsi nyata. Mungkin saya hanya takut pemrograman fungsional. ;)
MikeD
@miked: ceritakan lebih banyak. apa gvr dan apa modul operator? bisakah Anda memposting tautan? saya mungkin mengenal orang lain, tapi saya masih perantara di python. berminat untuk belajar! :-)
eruciform
GvR adalah Guido van Rossum, diktator kebajikan Python untuk seumur hidup. Berikut ini adalah pos berusia lima tahun dari dia yang menjelaskan mengapa lisp-isme (peta, filter, kurangi, lambda) tidak memiliki banyak tempat di python maju, dan alasan-alasan itu masih berlaku sampai sekarang. Modul operator memiliki penggantian untuk mengekstraksi anggota : "lambda x: x [1]" dibandingkan dengan "itemgetter (1)" adalah karakter yang lebih panjang dan bisa dibilang membutuhkan waktu lebih lama untuk dipahami. Saya kehabisan ruang, tetapi ajukan pertanyaan!
MikeD
@miked: ingin gigitan pertama pada apel? stackoverflow.com/questions/3292481/...
eruciform
Mereka benar-benar tidak perlu mengimplementasikan sesuatu bawaan ( min()).
Eric O Lebigot
-8

Apa ini yang kamu cari?

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

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

Cetakan 'empat belas'

pengguna365363
sumber
8
-1: bukan pertanyaannya. Anda mengembalikan nilai dengan kunci minimum, OP ingin kunci dengan nilai minimum
Brian S