lambda is an anonymous function, it is equivalent to:
def func(p):
return p.totalScore
Now max becomes:
max(players, key=func)
But as def statements are compound statements they can't be used where an expression is required, that's why sometimes lambda's are used.
Note that lambda is equivalent to what you'd put in a return statement of a def. Thus, you can't use statements inside a lambda, only expressions are allowed.
What does max do?
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item. With two or more arguments, return the largest argument.
So, it simply returns the object that is the largest.
How does key work?
By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).
To modify the object before comparison, or to compare based on a particular attribute/index, you've to use the key argument.
Example 1:
A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.
>>> lis = ['1', '100', '111', '2']
Here max compares the items using their original values (strings are compared lexicographically so you'd get '2' as output) :
>>> max(lis)
'2'
To compare the items by their integer value use key with a simple lambda:
>>> max(lis, key=lambda x:int(x)) # compare `int` version of each item
'111'
Example 2: Applying max to a list of tuples.
>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]
By default max will compare the items by the first index. If the first index is the same then it'll compare the second index. As in my example, all items have a unique first index, so you'd get this as the answer:
>>> max(lis)
(4, 'e')
But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:
>>> max(lis, key = lambda x: x[1])
(-1, 'z')
Comparing items in an iterable that contains objects of different type:
List with mixed items:
lis = ['1','100','111','2', 2, 2.57]
In Python 2 it is possible to compare items of two different types:
>>> max(lis) # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x)) # compare integer version of each item
'111'
But in Python 3 you can't do that any more:
>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
max(lis)
TypeError: unorderable types: int() > str()
But this works, as we are comparing integer version of each object:
>>> max(lis, key=lambda x: int(x)) # or simply `max(lis, key=int)`
'111'
Answer from Ashwini Chaudhary on Stack Overflowlambda is an anonymous function, it is equivalent to:
def func(p):
return p.totalScore
Now max becomes:
max(players, key=func)
But as def statements are compound statements they can't be used where an expression is required, that's why sometimes lambda's are used.
Note that lambda is equivalent to what you'd put in a return statement of a def. Thus, you can't use statements inside a lambda, only expressions are allowed.
What does max do?
max(a, b, c, ...[, key=func]) -> value
With a single iterable argument, return its largest item. With two or more arguments, return the largest argument.
So, it simply returns the object that is the largest.
How does key work?
By default in Python 2 key compares items based on a set of rules based on the type of the objects (for example a string is always greater than an integer).
To modify the object before comparison, or to compare based on a particular attribute/index, you've to use the key argument.
Example 1:
A simple example, suppose you have a list of numbers in string form, but you want to compare those items by their integer value.
>>> lis = ['1', '100', '111', '2']
Here max compares the items using their original values (strings are compared lexicographically so you'd get '2' as output) :
>>> max(lis)
'2'
To compare the items by their integer value use key with a simple lambda:
>>> max(lis, key=lambda x:int(x)) # compare `int` version of each item
'111'
Example 2: Applying max to a list of tuples.
>>> lis = [(1,'a'), (3,'c'), (4,'e'), (-1,'z')]
By default max will compare the items by the first index. If the first index is the same then it'll compare the second index. As in my example, all items have a unique first index, so you'd get this as the answer:
>>> max(lis)
(4, 'e')
But, what if you wanted to compare each item by the value at index 1? Simple: use lambda:
>>> max(lis, key = lambda x: x[1])
(-1, 'z')
Comparing items in an iterable that contains objects of different type:
List with mixed items:
lis = ['1','100','111','2', 2, 2.57]
In Python 2 it is possible to compare items of two different types:
>>> max(lis) # works in Python 2
'2'
>>> max(lis, key=lambda x: int(x)) # compare integer version of each item
'111'
But in Python 3 you can't do that any more:
>>> lis = ['1', '100', '111', '2', 2, 2.57]
>>> max(lis)
Traceback (most recent call last):
File "<ipython-input-2-0ce0a02693e4>", line 1, in <module>
max(lis)
TypeError: unorderable types: int() > str()
But this works, as we are comparing integer version of each object:
>>> max(lis, key=lambda x: int(x)) # or simply `max(lis, key=int)`
'111'
Strongly simplified version of max:
def max(items, key=lambda x: x):
current = item[0]
for item in items:
if key(item) > key(current):
current = item
return current
Regarding lambda:
>>> ident = lambda x: x
>>> ident(3)
3
>>> ident(5)
5
>>> times_two = lambda x: 2*x
>>> times_two(2)
4
Why does min() in Python return the key when a lambda is used on dictionaries? - Stack Overflow
Allow `min()` and `max()` to return both the key and value - Ideas - Discussions on Python.org
[Python] Question! I am having trouble with min/max
python - What is the correct use of "key" in the min() function? - Stack Overflow
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 keys1), as if each keykhad 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()).
I am supposed to write my own min/max functions. They should be able to deal with ints, strings, lists, and whatnot. I'm having trouble. Firstly, if my input is a list, how do I ignore the list and simply look at the numbers/letters inside? My other, more confusing question is:
min([[1, 2], [3, 4], [9, 0]], key=lambda x: x[1]) == [9, 0], "lambda key"
It says the output should be [9, 0] if I input:
min([[1, 2], [3, 4], [9, 0]], key=lambda x: x[1])
I do't understand what key or lambda means, even after reading about them. And then the x: x[1] makes it extra confusing. Can anyone help me?
The code is using the min builtin function, but with a key parameter. Thus, it does not return the actual minimum element of the list, but the element for which that key function is minimal, i.e. it behaves more like "arg-min" than actually "min".
In the key function (defined as a lambda expression), abs is just the absolute difference, in this case between the parameter x (a number from the list) and 5.
That line is somewhat equivalent to, but much shorter and more readable than, this loop:
a = [1,3,4,7,8,9,12,13,14]
b = min_k = None
for x in a:
k = abs(x-5)
if min_k is None or k < min_k:
b, min_k = x, k
Explanation
min(iterable, key) returns the smallest item in the iterable with respect to the key. So it iterates over the iterable, each time evaluates the key(x) for an element x, and then returns the element for which key(x) was the smallest.
Since key=lambda x=abs(x-5), we thus evaluate the absolute difference between 5, so if x=3, then abs(x-5) is 2, etc. So this will result in the number that is the closest to 5.
Making this an O(log n) algorithm
Given the list is ordered, you can find this in logarithmic time with:
from bisect import bisect_left
def closest(ordered_list, x):
idx = bisect_left(ordered_list, x)
return min(ordered_list[max(idx-1,0):idx+1], key=lambda y: abs(y-x))
For example:
>>> closest(a, -1)
1
>>> closest(a, 0)
1
>>> closest(a, 1)
1
>>> closest(a, 2)
1
>>> closest(a, 3)
3
>>> closest(a, 4)
4
>>> closest(a, 5)
4
>>> closest(a, 6)
7
>>> closest(a, 11)
12
>>> closest(a, 15)
14