views:

286

answers:

9

If I have a Python dictionary, how do I get the key to the entry which contains the minimum value?

I was thinking about something to do with the min() function...

Given the input:

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

It would return 321.

Any ideas?
Thanks!

+1  A: 

Edit: this is an answer to the OP's original question about the minimal key, not the minimal answer.


You can get the keys of the dict using the keys function, and you're right about using min to find the minimum of that list.

perimosocordiae
Not really deserving a downvote, as the poster's original question wasn't as clear as it might have been.
GreenMatt
@Space_C0wb0y: perhaps you can be so kind to notice that the OP edited his question to mean something different, after I answered
Eli Bendersky
+7  A: 

Here's an answer that actually gives the solution the OP asked for:

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

Using d.iteritems() will be more efficient for larger dictionaries, however.

Mark Rushakoff
Thanks! That's perfect :)
blob8108
Instead of the lambda you can use `operator.itemgetter(1)`.
Philipp
A: 

Is this what you are looking for?

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

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

Prints 'fourteen'

-1: not what the question asked. You're returning the value with the minimum key, OP wants key with the minimum value
Brian S
+2  A: 

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

abyx
A: 
# python 
d={320:1, 321:0, 322:3}
reduce(lambda x,y: x if d[x]<=d[y] else y, d.iterkeys())
  321
eruciform
-1 for reduce in python
MikeD
@miked: why the reduce-hate?
eruciform
1)Reduce is generally slower than itertools. 2)Most implementations of reduce can be done simpler with any or all. 3)I am a giant mouthpiece for GvR. 4)The operator module makes most simple lambdas unnecessary, and complex lambdas should be defined as real functions anyway. Maybe I'm just scared of functional programming. ;)
MikeD
@miked: tell me more. what's gvr and what's the operator module? could you post links? i may know others, but i'm still just an intermediate in python. willing to learn! :-)
eruciform
GvR is Guido van Rossum, Python's benevolent dictator for life. Here's a [five year old post](http://www.artima.com/weblogs/viewpost.jsp?thread=98196) from him explaining why lisp-isms (map,filter,reduce,lambda) don't have much of a place in python going forward, and those reasons are still true today. The operator module has replacements for [extracting members](http://docs.python.org/library/operator.html#operator.attrgetter): "lambda x: x[1]" compared to "itemgetter(1)" is a character longer and arguably takes longer to understand. I'm out of space, but ask questions!
MikeD
@miked: want first bite at the apple? http://stackoverflow.com/questions/3292481/most-important-python-optimizations
eruciform
A: 
>>> d = {320:1, 321:0, 322:3}
>>> min(d, key=lambda k: d[k]) 
321
Daniel Stutzbach
did you actually run this?
SilentGhost
It works, but gives the result 321, not (321, 0) ?
blob8108
@SilentGhost, @blob8108: D'oh! Copy-and-paste snafu. Fixed now.
Daniel Stutzbach
+17  A: 

Best: min(d, key=d.get) -- no reason to interpose a useless lambda indirection layer or extract items or keys!

Alex Martelli
This seems to be the simplest correct answer so far.
Brian S
+1: Clever! Probably slower than itemgetter but incredibly elegant!
MikeD
@Mike: how would you use `itemgetter` here? Besides, I think it's the fastest solution.
SilentGhost
Like this very much, I hadn't thought of it. Thanks for the answer, +1
ThE_JacO
@SilentGhost: You wouldn't, I'm not sure what I was thinking.
MikeD
A: 

If you are not sure that you have not multiple minimum values, I would suggest:

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

Another approach to addressing the issue of multiple keys with the same min value:

>>> 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]
Paul McGuire