2010-07-19 13 views
165

Se ho un dizionario Python, come posso ottenere la chiave della voce che contiene il valore minimo?Ottieni la chiave corrispondente al valore minimo all'interno di un dizionario

stavo pensando a qualcosa a che fare con la funzione min() ...

Dato l'ingresso:

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

Sarebbe tornare 321.

+0

Errore di battitura nel reso dichiarato? Altrimenti, perché 321? Non dovrebbe essere 320? – GreenMatt

+2

@myself: Ok, ora vedo - ciò che si desidera è la chiave della voce in cui il valore della voce è il minimo. Migliore formulazione della domanda per favore, dato che gli altri ovviamente pensavano la stessa cosa che ho fatto io. – GreenMatt

+1

Giorno di sensibilizzazione della struttura dei dati: se si interroga (o rimuovi) solo l'elemento minimo, si consideri l'utilizzo di una coda o heap di priorità. –

risposta

332

migliore: min(d, key=d.get) - alcun motivo di interporre uno strato lambda indirezione inutile o estrarre gli elementi o le chiavi!

+0

+1: intelligente! Probabilmente più lento di itemgetter ma incredibilmente elegante! – MikeD

+0

@Mike: come useresti 'itemgetter' qui? Inoltre, penso che sia la soluzione più veloce. – SilentGhost

+3

@ SilentGhost: non lo faresti, non sono sicuro di cosa stavo pensando. – MikeD

3

Edit: questa è una risposta alla domanda iniziale del PO sulla chiave minimal, non è la risposta minima.


È possibile ottenere le chiavi del dict utilizzando la funzione keys, e hai ragione sull'utilizzo min per trovare il minimo di tale elenco.

+0

Non merita davvero un downvote, perché la domanda originale del poster non era chiara come avrebbe potuto essere. – GreenMatt

+0

@ Space_C0wb0y: forse puoi essere così gentile da notare che l'OP ha modificato la sua domanda per indicare qualcosa di diverso, dopo aver risposto a –

34

Ecco una risposta che in realtà dà la soluzione del PO ha chiesto:

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

Utilizzando d.iteritems() sarà più efficiente per i dizionari più grandi, però.

+3

Invece di lambda puoi usare 'operator.itemgetter (1)'. – Philipp

+1

invece usare lamda d.get – Texom512

+0

Questo non restituisce la chiave come richiesto, ma la coppia (chiave, valore). – EOL

-6

È questo quello che stai cercando?

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

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

Stampe 'quattordici'

+8

-1: non è quello che la domanda ha posto. Stai restituendo il valore con la chiave minima, OP vuole chiave con il valore minimo –

7

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

-1
# python 
d={320:1, 321:0, 322:3} 
reduce(lambda x,y: x if d[x]<=d[y] else y, d.iterkeys()) 
    321 
+0

-1 per riduci in python – MikeD

+0

@miked: perché ridurre-odio? – eruciform

+5

1) La riduzione è generalmente più lenta di itertools. 2) La maggior parte delle implementazioni di riduzione può essere eseguita più semplicemente con qualsiasi o tutte. 3) Sono un bocchino gigante per GvR. 4) Il modulo operatore rende inutili i lambd più semplici, mentre i lambda complessi devono essere definiti come funzioni reali. Forse ho solo paura della programmazione funzionale. ;) – MikeD

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

hai effettivamente eseguito questo? – SilentGhost

+0

Funziona, ma fornisce il risultato 321, non (321, 0)? – tjvr

+0

@SilentGhost, @ blob8108: D'oh! Copia e incolla snafu. Risolto ora. –

2

Se non si è sicuri di non aver più valori minimi, vorrei suggerire:

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

Un altro approccio per affrontare la questione di più chiavi con lo stesso valore 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

Utilizzare min con un iteratore (per python 3 utilizzare items anziché iteritems); invece di lambda utilizzare l'operatore itemgetter, che è più veloce di lambda.

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

Per il caso in cui si dispone di più chiavi minime e si desidera mantenere le cose semplici

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'] 
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] 
+0

Qualche idea su come calcolare il valore più basso SOPRA zero? –

0

ho confrontato come i seguenti tre opzioni eseguono: uscita

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) 

Campione :

#option 1 
236230 
0:00:14.136808 

#option 2 
236230 
0:00:00.458026 

#option 3 
236230 
0:00:00.824048 
Problemi correlati