รับรหัสที่สอดคล้องกับค่าต่ำสุดภายในพจนานุกรม


305

หากฉันมีพจนานุกรม Python ฉันจะรับกุญแจไปยังรายการที่มีค่าต่ำสุดได้อย่างไร

ฉันคิดว่าจะทำอะไรกับmin()ฟังก์ชั่น ...

รับอินพุต:

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

321มันจะกลับมา


พิมพ์ผิดในผลตอบแทนที่คุณระบุ? มิฉะนั้นทำไม 321 ไม่ควร 320
GreenMatt

3
@ ตัวเอง: โอเคตอนนี้ฉันเห็น - สิ่งที่ต้องการคือกุญแจสำคัญในรายการที่มูลค่าของรายการเป็นขั้นต่ำ กรุณาใช้ถ้อยคำให้เป็นคำถามที่ดีกว่าเนื่องจากคนอื่นคิดอย่างเดียวกันกับที่ฉันทำ
GreenMatt

2
วันที่รับรู้โครงสร้างข้อมูล: หากคุณเคยค้นหา (หรือลบ) องค์ประกอบขั้นต่ำเท่านั้นให้ลองใช้ลำดับความสำคัญหรือฮีป
พันเอก Panic

คำตอบ:


597

ดีที่สุด: 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 [key] [0]
TrakJohnson

4
มันทำงานอย่างไร ฟังก์ชัน min ชนิดใดที่ฉันคิดว่า min () รับเฉพาะค่าหรือแต่ละรายการเป็นอาร์กิวเมนต์ มันวนซ้ำทุกรายการในพจนานุกรมได้อย่างไร
azureai

2
min()ส่งคืนค่าในค่าแรกในการเรียงลำดับ สำคัญกำหนดวิธีการเรียงลำดับค่า key=d.getหมายถึงรายการจะถูกจัดเรียงตามค่าของพจนานุกรม
notilas

45

ต่อไปนี้เป็นคำตอบที่ให้คำตอบสำหรับ 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)

อย่างไรก็ตามการใช้d.iteritems()จะมีประสิทธิภาพมากขึ้นสำหรับพจนานุกรมขนาดใหญ่


3
operator.itemgetter(1)แทนที่จะแลมบ์ดาคุณสามารถใช้
ฟิลิปป์

2
lamda ใช้ d.get แทน
Texom512

สิ่งนี้ไม่ส่งคืนคีย์ตามที่ถาม แต่คู่ (คีย์ค่า)
Eric O Lebigot

14

สำหรับหลายคีย์ที่มีค่าต่ำสุดเท่ากันคุณสามารถใช้ list comprehension:

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
>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321

@SilentGhost, @ blob8108: D'oh! คัดลอกและวาง Snafu แก้ไขแล้ว
Daniel Stutzbach

ฉันคิดว่าวิธีแก้ปัญหาที่ดี แต่ฟังก์ชั่นที่ไม่ระบุชื่อจะเพิ่มเลเยอร์ทางอ้อมเท่านั้น: key=d.getดีกว่า
Eric O Lebigot

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

แก้ไข:นี่คือคำตอบสำหรับคำถามดั้งเดิมของ OP เกี่ยวกับคีย์ขั้นต่ำไม่ใช่คำตอบขั้นต่ำ


คุณสามารถรับคีย์ของ dict โดยใช้keysฟังก์ชันและคุณถูกต้องเกี่ยวกับการใช้minเพื่อค้นหาขั้นต่ำของรายการนั้น


ไม่สมควรได้รับการโหวตเพราะคำถามดั้งเดิมของผู้โพสต์นั้นไม่ชัดเจนเท่าที่ควร
GreenMatt

@ Space_C0wb0y: บางทีคุณอาจจะสังเกตเห็นได้ว่า OP ได้แก้ไขคำถามของเขาให้มีความหมายที่แตกต่างออกไปหลังจากที่ฉันตอบ
Eli Bendersky

3

อีกวิธีในการแก้ไขปัญหาของหลาย ๆ คีย์ด้วยค่า min ขั้นต่ำ:

>>> 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กับ iterator (สำหรับ 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 เพื่อสร้างตัววนซ้ำของ tuples ที่มีค่าและคีย์ จากนั้นห่อมันด้วยฟังก์ชั่นขั้นต่ำซึ่งใช้เวลาน้อยที่สุดตามคีย์แรก สิ่งนี้จะคืนค่า tuple ที่มีคู่ (value, key) ดัชนีของ [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) โมดูลตัวดำเนินการทำให้ lambdas ที่ง่ายที่สุดไม่จำเป็นและ lambdas ที่ซับซ้อนควรถูกกำหนดเป็นฟังก์ชั่นจริงต่อไป บางทีฉันแค่กลัวการเขียนโปรแกรมที่ใช้งานได้ ;)
MikeD

@ Miked: บอกฉันมากกว่านี้ gvr คืออะไรและโมดูลตัวดำเนินการคืออะไร คุณโพสต์ลิงก์ได้ไหม ฉันอาจรู้จักคนอื่น แต่ฉันก็ยังเป็นแค่สื่อกลางในหลาม ยินดีที่จะเรียนรู้! :-)
eruciform

GvR คือกุยโดแวนรอสซัมเผด็จการผู้มีเมตตาของไพ ธ อนตลอดชีวิต ต่อไปนี้เป็นบทความห้าปีจากเขาอธิบายว่าทำไม lisp-isms (แผนที่, ตัวกรอง, ลด, แลมบ์ดา) ไม่มีสถานที่ใดในงูเหลือมเดินหน้าต่อไปและเหตุผลเหล่านั้นยังคงเป็นจริงในปัจจุบัน โมดูลตัวดำเนินการมีการแทนที่สำหรับการแยกสมาชิก : "lambda x: x [1]" เปรียบเทียบกับ "itemgetter (1)" เป็นอักขระที่ยาวกว่าและเนื้อหาใช้เวลาในการทำความเข้าใจนานกว่า ฉันออกไปนอกพื้นที่ แต่ถามคำถาม!
MikeD

@ Miked: ต้องการกัดที่แอปเปิ้ลก่อน? stackoverflow.com/questions/3292481/…
eruciform

พวกเขาไม่จำเป็นต้องปรับใช้สิ่งที่สร้างไว้ใน ( min()) อีกครั้ง
Eric O Lebigot

-8

นี่คือสิ่งที่คุณกำลังมองหา?

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

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

พิมพ์ 'สิบสี่'


8
-1: ไม่ใช่คำถามที่ถาม คุณคืนค่าด้วยคีย์ต่ำสุด OP ต้องการคีย์ด้วยค่าต่ำสุด
Brian S
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.