How does this lambda to sort numbers work?

#code for sorting big integers lis = ['234', '5', '2', '12435645758'] lis.sort(key = lambda x: len(x)) print lis #output ['5', '2', '234', '12435645758'] lis.sort(key = lambda x: (len(x), x)) print lis #output ['2', '5', '234', '12435645758'] 

I am trying to sort large numeric strings in Python without converting strings to integers and could not understand how this lambda expression is evaluated.

The first lambda expression sorts by the length of the string and sorts the list, but what does the second do? I would like to know how the second lambda expression is evaluated.

+5
source share
2 answers

The lambda returns a tuple for each value in the list. These tuples are then used to indicate the sort order. Therefore, instead of comparing '234' with '5' , the sorting algorithm is proposed to compare (3, '234') and (1, '5') .

Python sorts the tuples lexicographically , that is, first comparing the first elements of two tuples, then if they match, moving to compare the second elements, etc., until there are no elements that can be compared.

Since the tuple contains both the length and the string, for strings of equal length, the strings are sorted as follows according to their actual value. This puts longer lines at the end, shorter lines in front and inside each group of equal length lines are sorted by their value.

Looking again at your input example, for '234' and '5' , the resulting tuples (3, '234') and (1, '5') have unequal first elements, so (1, '5') sorted to (3, '234') . But for '5' and '2' resulting tuples (1, '5') and (1, '2') (both have a length of 1 character), and the first elements of these tuples are equal. Therefore, they are sorted by the second element, placing '2' to '5' .

Without such switches (so the keys are equal), Python leaves the relative order intact. For the first example, the sort key is simply len(x) , and since '5' and '2' are the same length and there is nothing to compare them, Python puts them in the output in the same relative order, '5' to '2' .

+2
source

Tuples, lists and strings compare them to "Lexicographic order (Wikipedia link) . " This means that they compare elements for equality , starting from the left. As soon as one element is not equal, they are compared if this element is smaller or larger.

In the second sort you create a tuple containing the length and then the string . Therefore, if you compare two elements, it will check: if the length is unequal, a shorter one will be considered β€œless”. If the length is equal to the number with the bottom "string representation", it is "less".

This is roughly equivalent to sorting by length first and then string representation:

 lis = ['234', '5', '2', '12435645758'] class StringInteger(object): def __init__(self, string): self.string = string def __lt__(self, other): """ that the method that implements "smaller than": < comparisons.""" # check if the lengths are equal if len(self.string) == len(other.string): # lengths are equal, so compare the strings return self.string < other.string else: # lengths are not equal, compare the lengths return len(self.string) < len(other.string) sorted(lis, key=StringInteger) # ['2', '5', '234', '12435645758'] 
+1
source

Source: https://habr.com/ru/post/1268317/


All Articles