Reputation: 13
I have the following list:
l = ['hey (0)', 'hey (1)', 'bye (3)', 'bye (1)']
And I want to sort it firstly by the numerical character and then alphabeticly
The output should be:
l = ['hey (0)','bye (1)', 'hey (1)', 'bye (3)']
tried:
l.sort(key = lambda x: (x[-2], x[1]))
Any ideas?
Upvotes: 1
Views: 33
Reputation: 1728
Your approach is nearly correct. One mistake is that x[1]
sorts elements with the same numeric value by the second letter, not the first.
Your solution also does generalize well to other inputs. For example, it might place "produce (5)"
after "product (5)"
because you are not looking at all of the letters in the word.
You should use the entire beginning of the string (x[:-4]
will cut off the number, parentheses, and space), and optionally convert the numbers to integers:
>>> l = ['hey (0)', 'hey (1)', 'bye (3)', 'bye (1)']
>>> l.sort(key=lambda x: (int(x[-2]), x[:-4]))
>>> l
['hey (0)', 'bye (1)', 'hey (1)', 'bye (3)']
This is still not fully general - for instance, it only works if the numbers are guaranteed to be integers between 0 and 9, otherwise "foo (11)"
may appear smaller than "foo (9)"
. In that case, you may want to use something more like azro's solution.
Upvotes: 1
Reputation: 54148
You need to more precise x[-2]
takes the digit (but as a string) but x[1]
takes the 2nd char, you need the whole word, a regex could do it nicely
import re
pattern = re.compile("(\w+) \((\d+)\)")
def sorter(value):
text, nb = pattern.findall(value)[0]
return int(nb), text
l = ['hey (0)', 'hey (1)', 'bye (3)', 'bye (1)']
l.sort(key=sorter)
print(l) # ['hey (0)', 'bye (1)', 'hey (1)', 'bye (3)']
Or without regex
def sorter(value):
text, nb = value.split(" ")
return int(nb.strip("()")), text
l = ['hey (0)', 'hey (1)', 'bye (3)', 'bye (1)']
l.sort(key=sorter)
print(l) # ['hey (0)', 'bye (1)', 'hey (1)', 'bye (3)']
Upvotes: 0