I am studying the Python Cookbook, 3rd edition. I encountered the code below:
prices = {'ACME': 45.23,'AAPL': 612.78,'IBM': 205.55,'HPQ': 37.20,'FB': 10.75}
min(prices, key=lambda k: prices[k])
I tested this on Python 3.6.0, and it returns 'FB'.
My understanding is that every key from the prices
dictionary is sent to the lambda as parameter k
and then the lambda returns the value associated with key k
in the prices
dictionary. So after iterating through all the keys, a list of values is returned which is used as an argument to the min
function which finally returns the minimum value (in this case 10.75) in the dictionary.
But when I ran the code, the program printed out the key (in this case 'FB'). Where am I wrong?
I have gone through the documentation. It said min
returns the smallest item in an iterable. I know min
processes the keys and not the values. I just don't understand how it returns the key when the lambda returns a list of values. Help me please.
EDIT : Sorry for the edit. I am trying to find the key of the smallest value in the dictionary. The above code works perfectly but I don't know how it works.
You are correct that the lambda
function you defined will be applied to all the keys, however that does not mean that min
will return whatever your lambda
function may return.
Perhaps it's helpful to spell out the line
min(prices, key=lambda k: prices[k])
in words:
"Find the minimum of the iterable
prices
(the dictionary keys 1 ), as if each keyk
had the valueprices[k]
."
If you want the associated value, you can use the returned key to access prices
>>> prices[min(prices, key=lambda k: prices[k])]
>>> 10.75
or much shorter:
>>> min(prices.values())
>>> 10.75
1 Because a dictionary is an iterable of keys ( list(prices)
gives a list of keys).
why min() in python returns key when lambda is used on dictionaries
Because iterating dictionaries iterates over the keys in arbitrary order. The key
parameter is NOT a map parameter.
If you want the minimum value, then take
min(prices.items())
min(prices.values())
.
When you iterate through a dictionary (as you are doing implicitly with min()
), it uses the keys. min(prices)
is equivalent to min(prices.keys())
. So min()
iterates through each of the KEYS in the dictionary, and uses the lambda function to compare them. It returns one of the items in what it is iterating over - so one of the keys.
If you want the items instead, you can use min(prices.items())
, no key needed.
If you want both, I would just use what you have an get the price with the returned key.
The thing you supply as key
is merely used to sort the iterable you give it - in your case all the keys of the dictionary - you get "the one" returned that is lowest according to your key-definition
.
Example:
data = ["a","bb","ccc","dddd"]
print( min( data, key = lambda x: -len(x))) # get the min value by negative length ascending
Prints:
dddd
because the elements of the list got evaluated according to theire respective negative length:
['a', 'bb', 'ccc', 'dddd'] # iterable
[ -1, -2 , -3, -4 ] # the key-result
and the minimal ones from the iterable was returned: 'dddd'
If you want both the key and the value, you can use:
>>> min(prices.items(), key=lambda kv: kv[1])
('FB', 10.75)
min
returns the smallest item of an iterable. To decide what elements are smaller, it uses the key. Here, you're asking for the minimum of prices
, so it returns the smallest element of that iterable. The key just tells min
to use that key in deciding which items of the iterable are smaller; min
still uses the values of the iterable, not the key applied to the values, as the minimum to return. Imagine if someone says "Tell me what country is largest by population". The correct answer is "China", not 1.386 billion. 1.386 billion is the value used to decide that China is "largest", not the thing that is largest. When you write min(iterable, key=key)
, you are asking for the smallest of iterable
by key
, not the smallest key
. Basically, min
is equivalent to the following:
def min(iterable, key = lambda x:x):
cur_min = iterable.first
for item in iterable:
if key(item)<key(cur_min):
cur_min = item
return cur_min
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.