Since the first element in each tuple is a string, Python is performing lexographic sorting in which all strings that start with '1'
come before strings that start with a '2'
.
To get the sorting you desire, you'll want to treat the first entry as a float
instead of a string.
We can use sorted
along with a custom sorting function which converts the first entry to a float prior to sorting. It also keeps the second tuple element to handle the case when you may have non-unique first entries.
result = sorted(L, key = lambda x: (float(x[0].split()[0]), x[1]))
# [('1', 'blaabal'), ('1.2', 'bbalab'), ('2.1', 'baala'), ('3', 'yuio'), ('4', 'poku'), ('5.2', 'qsdfg'), ('10', 'ejej'), ('11.1', 'aaua'), ('12.1', 'ehjej'), ('12.2 (c)', 'ekeke'), ('12.2 (d)', 'qwerty')]
I had to add in a x[0].split()[0]
so that we split the first tuple element at the space and only grab the first pieces since some have values such as '12.2 (d)'
and we only want the '12.2'
.
If the second part of that first element that we've discarded matters, then you could use a sorting function similar to the following which breaks that first element into pieces and converts just the first piece to a float and leaves the rest as strings.
def sorter(value):
parts = value[0].split()
# Convert the first part to a number and leave all other parts as strings
parts[0] = float(parts[0]);
return (parts, value[1])
result = sorted(L, key = sorter)