Can't understand the lambda function inside the sorted() key argument

Question:

I have to sort a string in this order:

  • All sorted lowercase letters are ahead of uppercase letters.
  • All sorted uppercase letters are ahead of digits.
  • All sorted odd digits are ahead of sorted even digits.

For instance, when the input is "Sample6789", the output must be "aelmpS7968."

The code that solved this problem was the following:

s = 'Sample6789'
print("".join(sorted(s, key=lambda x: (x.isdigit(), x.isdigit() and int(x)%2==0, x.isupper(), x))))

So, as far as I understand, the lambda function checks whether it’s digit, even, and uppercase or not, and returns it. But I am not sure how it actually iterates through every letter/digit and returns the desired output. For example, if I understand correctly, the first letter "S" gets tuple of (False – not integer, False – not integer and not even, True – upper Case, S – itself). But after that, I have no clue how is it returning the correct output.

Asked By: Jagernout1985

||

Answers:

As the comment notes: tuples are sorted such that False is ordered before True

first x = "S" --> (False, False, True, "S")
        = "a" --> (False, False, False, "a")
        = "m" --> (False, False, False, "m")
        = "p" --> (False, False, False, "p")
        = "l" --> (False, False, False, "l")
        = "e" --> (False, False, False, "e")
        = "6" --> (True, True, False, "6")
        = "7" --> (True, False, False, "7")
        = "8" --> (True, True, False, "8")
        = "9" --> (True, False, False, "9")
    

so

sorted(s, key=lambda x: (x.isdigit(), x.isdigit() and int(x)%2==0, x.isupper(), x))

gives:

['a', 'e', 'l', 'm', 'p', 'S', '7', '9', '6', '8']

then .join() — does this help?

Answered By: yukako

The sorted() function sorts the elements of a given iterable in ascending order by default. However, you can also pass a key function to sort the elements based on a specific criterion. In your case, the key function is a lambda function that returns a tuple of values for each character in the string s.

lambda x: (x.isdigit(), x.isdigit() and int(x)%2==0, x.isupper(), x)

For each character x in the string s, the lambda function returns a tuple of four values:

x.isdigit(): This value is True if x is a digit, otherwise False.
x.isdigit() and int(x)%2==0: This value is True if x is a digit and is even, otherwise False.
x.isupper(): This value is True if x is an uppercase letter, otherwise False.
x: This is the original character itself.
The sorted() function uses this tuple of values to determine the order of the elements in the output string. The elements will be sorted in ascending order based on the values of the tuple.

In above example input string "Sample6789". The first character is "S", which is an uppercase letter. The lambda function returns the tuple (False, False, True, "S") for this character. Since this is the first character, it will come first in the sorted output string.

The second character is "a", which is a lowercase letter. The lambda function returns the tuple (False, False, False, "a") for this character. Since all lowercase letters come before uppercase letters, this character will come before the first character in the sorted output string.

Similarly, the rest of the characters are sorted based on the values returned by the lambda function. This results in the desired output "aelmpS7968", where all lowercase letters come before uppercase letters, all uppercase letters come before digits, and odd digits come before even digits.

I hope this explanation helps you understand how the lambda function works and how the sorted() function uses it to sort the input string.

Answered By: iamkw97
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.