Holen Sie sich den Schlüssel, der dem Mindestwert in einem Wörterbuch entspricht


305

Wie bekomme ich den Schlüssel zu dem Eintrag, der den Mindestwert enthält, wenn ich ein Python-Wörterbuch habe?

Ich habe über etwas nachgedacht, das mit der min()Funktion zu tun hat ...

Angesichts der Eingabe:

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

Es würde zurückkehren 321.


Tippfehler in Ihrer angegebenen Rendite? Warum sonst 321? Sollte es nicht 320 sein?
GreenMatt

3
@myself: Okay, jetzt verstehe ich - was gewünscht wird, ist der Schlüssel zum Eintrag, bei dem der Wert des Eintrags das Minimum ist. Bitte formulieren Sie die Frage besser, da andere offensichtlich genauso dachten wie ich.
GreenMatt

2
Tag der Datenstrukturerkennung: Wenn Sie immer nur das Mindestelement abfragen (oder entfernen), sollten Sie eine Prioritätswarteschlange oder einen Heap verwenden.
Colonel Panic

Antworten:


597

Am besten: min(d, key=d.get)- kein Grund, eine nutzlose lambdaIndirektionsebene einzulegen oder Elemente oder Schlüssel zu extrahieren!


5
@ KarelBílek bedeutet, dass Sie als "d" eine Liste übergeben haben [11, 22, 33], z {1: 11, 2:22, 3:33}. B. anstelle eines Wörterbuchs, z . 'd.get' gilt für ein Wörterbuch, jedoch nicht für eine Liste.
ToolmakerSteve

9
Was ist, wenn zwei verschiedene Schlüssel den gleichen Wert haben? und sie sind beide der kleinste Wert? Wie können Sie dafür sorgen, dass beide zurückgegeben werden?
user3226932

5
Kann diese Technik verwendet werden, wenn die Diktatwerte Listen sind, z. B.: Wobei d={"a":[10, None], "b":[20, None]}die min aus d [Taste] [0] berechnet wird?
TrakJohnson

4
Wie funktioniert das? Was für eine min-Funktion ist das? Ich dachte, min () hat nur einzelne Werte oder Listen als Argumente verwendet. Wie werden alle Einträge im Wörterbuch durchlaufen?
Azureai

2
min()Geben Sie den Wert im ersten Wert in sortiert zurück. Schlüssel geben die Art und Weise an, wie die Werte sortiert werden. key=d.getbedeutet, dass die Liste nach Werten des Wörterbuchs sortiert wird.
Notilas

45

Hier ist eine Antwort, die tatsächlich die vom OP angeforderte Lösung liefert:

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

Die Verwendung d.iteritems()ist jedoch für größere Wörterbücher effizienter.


3
Anstelle des Lambda können Sie verwenden operator.itemgetter(1).
Philipp

2
stattdessen lamda benutze d.get
Texom512

Dies gibt nicht den angeforderten Schlüssel zurück, sondern das Paar (Schlüssel, Wert).
Eric O Lebigot

14

Für mehrere Schlüssel mit gleichem niedrigsten Wert können Sie ein Listenverständnis verwenden:

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]

Eine äquivalente funktionale Version:

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

1
Ihre Antwort ist sehr nützlich und andere sind sich wahrscheinlich einig: Siehe die mehrfachen Kommentare zu diesem Thema in der akzeptierten Antwort. Ich musste jedoch zweimal zurückkommen, um es zu finden: Würden Sie in Betracht ziehen, die akzeptierte Antwort zu bearbeiten? Ihre ist eigentlich komplementär.
jmon12


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

@ SilentGhost, @ blob8108: D'oh! Snafu kopieren und einfügen. Jetzt behoben.
Daniel Stutzbach

Gute Lösung, denke ich, aber die anonyme Funktion fügt nur eine Indirektionsebene hinzu: key=d.get ist besser.
Eric O Lebigot

6

Für den Fall, dass Sie mehrere Minimalschlüssel haben und es einfach halten möchten

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

Wenn Sie nicht sicher sind, dass Sie nicht mehrere Mindestwerte haben, würde ich vorschlagen:

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

Bearbeiten: Dies ist eine Antwort auf die ursprüngliche Frage des OP zum Minimalschlüssel, nicht zur Minimalantwort.


Mit der keysFunktion können Sie die Tasten des Diktats abrufen und mit Recht mindas Minimum dieser Liste ermitteln.


Nicht wirklich eine Ablehnung verdient, da die ursprüngliche Frage des Posters nicht so klar war, wie es hätte sein können.
GreenMatt

@ Space_C0wb0y: Vielleicht können Sie so freundlich bemerken, dass das OP seine Frage bearbeitet hat, um etwas anderes zu bedeuten, nachdem ich geantwortet habe
Eli Bendersky

3

Ein weiterer Ansatz zur Behebung des Problems mehrerer Schlüssel mit demselben Mindestwert:

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

Verwendung minmit einem Iterator (für Python 3 itemsanstelle von iteritems); Verwenden Sie anstelle von Lambda den itemgetterOperator from, der schneller als Lambda ist.

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


1

Ich habe verglichen, wie die folgenden drei Optionen funktionieren:

    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 )

Beispielausgabe:

#option 1
236230
0:00:14.136808

#option 2
236230
0:00:00.458026

#option 3
236230
0:00:00.824048

0

Um eine ordentliche Klasse zu erstellen, müssen Sie 6 Sonderfunktionen überschreiben, damit sie von der Funktion min () aufgerufen werden

Diese Methoden sind __lt__ , __le__, __gt__, __ge__, __eq__ , __ne__in der Reihenfolge, dass sie kleiner, kleiner oder gleich, größer als, größer oder gleich, gleich, nicht gleich sind. Sie sollten __lt__beispielsweise Folgendes implementieren :

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

dann können Sie die min-Funktion wie folgt verwenden:

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

das hat bei mir funktioniert.


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

Verwenden Sie die Zip-Funktion, um einen Iterator von Tupeln zu erstellen, der Werte und Schlüssel enthält. Wickeln Sie es dann mit einer Min-Funktion ein, die das Minimum basierend auf der ersten Taste annimmt. Dies gibt ein Tupel zurück, das ein Paar (Wert, Schlüssel) enthält. Der Index von [1] wird verwendet, um den entsprechenden Schlüssel zu erhalten


2
Während dieser Code die Frage möglicherweise beantwortet, verbessert die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie dieser Code die Frage beantwortet, ihren langfristigen Wert.
β.εηοιτ.βε

@ β.εηοιτ.βε das besser?
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) Reduzieren ist im Allgemeinen langsamer als itertools. 2) Die meisten Implementierungen von Reduce können mit einigen oder allen einfacher durchgeführt werden. 3) Ich bin ein riesiges Sprachrohr für GvR. 4) Das Operatormodul macht die meisten einfachen Lambdas unnötig, und komplexe Lambdas sollten sowieso als echte Funktionen definiert werden. Vielleicht habe ich nur Angst vor funktionaler Programmierung. ;)
MikeD

@miked: erzähl mir mehr. Was ist gvr und was ist das Operatormodul? Könntest du Links posten? Ich mag andere kennen, aber ich bin immer noch ein Zwischenprodukt in Python. bereit zu lernen! :-)
eruciform

GvR ist Guido van Rossum, Pythons wohlwollender Diktator fürs Leben. Hier ist ein fünf Jahre alter Beitrag von ihm, in dem erklärt wird, warum Lisp-Ismen (Map, Filter, Reduce, Lambda) in Python nicht viel Platz haben, und diese Gründe sind bis heute wahr. Das Operatormodul hat Ersetzungen zum Extrahieren von Elementen: "Lambda x: x [1]" im Vergleich zu "itemgetter (1)" ist ein Zeichen länger und das Verständnis dauert wahrscheinlich länger. Ich habe keinen Platz mehr, aber stelle Fragen!
MikeD

@miked: willst du zum ersten mal am apfel beißen? stackoverflow.com/questions/3292481/…
eruciform

Es ist wirklich nicht nötig, etwas Eingebautes ( min()) neu zu implementieren .
Eric O Lebigot

-8

Suchst du danach?

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

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

Druckt 'vierzehn'


8
-1: nicht was die Frage gestellt hat. Sie geben den Wert mit dem Mindestschlüssel zurück, OP möchte den Schlüssel mit dem Mindestwert
Brian S
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.