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.

tjvr
quelle
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!

Alex Martelli
quelle
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.

Mark Rushakoff
quelle
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))
jpp
quelle
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
11

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

Abyx
quelle
6
>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321
Daniel Stutzbach
quelle
@ 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']
Netskink
quelle
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
"""
Tony Veijalainen
quelle
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.

Eli Bendersky
quelle
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]
PaulMcG
quelle
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))
Antti Haapala
quelle
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
quelle
Irgendeine Idee, wie man den kleinsten Wert ÜBER Null berechnet?
Captain Anonymous
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
svinec
quelle
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.

Muhammad Korra
quelle
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

rajn
quelle
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
eruciform
quelle
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'

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