Reputation: 1351
Could someone please explain these lambdas? I am fairly confused by the following code and would appreciate some help understanding the code from someone who knows about this and can break the code down into understandable components.
convert = lambda text: int(text) if text.isdigit() else text
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(l, key = alphanum_key)
(source: https://arcpy.wordpress.com/2012/05/11/sorting-alphanumeric-strings-in-python/)
I understand the first lambda.
For the second lambda alphanum_key
I am confused. It seems that a key is passed in to the lambda and used in the split()
function in the re
module, but I do not see a key
passed into the alphanum_key
lambda when this lambda is called in the sorted()
function.
I wrote a small program to see if I could create normal def
functions out of the lambdas that are apparently using bad form by returning values and being called like functions. Here is my code:
import re
def convert2(text):
if text.isdigit():
return int(text)
else:
return text
def alphanum_key2(key):
a_list = []
for i in re.split('([0-9]+)', key):
a_list.append(convert2(i))
return a_list
if __name__ == "__main__":
things = ["10bags", "500miles", "10000maniacs", "2000lightYearsFromHome"]
x = sorted(things, key= alphanum_key2)
print(x)
#This prints
#['10bags', '500miles', '2000lightYearsFromHome', '10000maniacs']
convert = lambda text: int(text) if text.isdigit() else text
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
print(sorted(things, key = alphanum_key))
#This prints
#['10bags', '500miles', '2000lightYearsFromHome', '10000maniacs']
This leads to a second question... Why is the normal def
functions that mimic the lambda functions returning different and incorrect results. Please note the results returned in the comments of the code if you do not feel like running this program on your machine.
Upvotes: 2
Views: 272
Reputation: 308140
You say you understand the first function convert
so I won't go into that; just be aware that it returns either a string or an integer.
The straightforward conversion of the second from a lambda is:
def alphanum_key(key):
return [convert(c) for c in re.split('([0-9]+)', key)]
Let's break that down.
[... for ...]
That's a list comprehension. It will create a list containing an element for each iteration of the for
.
re.split('([0-9]+)', key)
This uses a regular expression consisting of all the digits ([0-9]
) repeated one or more times (+
). By putting parentheses around this expression those matches will be included in the output from split
.
>>> re.split('([0-9]+)', "10bags")
['', '10', 'bags']
There's an empty string at the beginning since split
splits apart the string at the matches and returns the parts both before and after the match.
The final output of alphanum_key
will be ['', 10, 'bags']
since '10'
will be converted to the integer 10
. This is important because you want to compare numbers:
>>> '10000' < '500'
True
>>> 10000 < 500
False
Upvotes: 1