I have a list of items that I would like to sort on multiple criterion.
Given input list:
cols = [
'Aw H',
'Hm I1',
'Aw I2',
'Hm R',
'Aw R',
'Aw I1',
'Aw E',
'Hm I2',
'Hm H',
'Hm E',
]
Criterions:
The output should be:
cols = [
'Hm I1',
'Aw I1',
'Hm I2',
'Aw I2',
'Hm R',
'Aw R',
'Hm H',
'Aw H',
'Hm E',
'Aw E'
]
I know this function needs to be passed onto the built-in sorted()
but any ideas how to actually write it?
Excel has Advanced Sorting options that can help you to perform multi-level sorting within a large database. Sometimes alphabetical or numerical Sorting do not suffice. In such cases, Advanced Sorting Options are required.
A custom sort is one you define. For instance, you might need to sort T-shirts by small, medium, large and extra-large. Or you might sort temperatures by cold, warm and hot. A regular sort can't handle these types of requirements.
You could write a function for the key, returning a tuple
with each portion of interest sorted by priority.
def k(s):
m = {'I':0, 'R':1, 'H':2, 'E':3}
return m[s[3]], int(s[4:] or 0), -ord(s[0])
cols = [
'Aw H',
'Hm I1',
'Aw I2',
'Hm R',
'Aw R',
'Aw I1',
'Aw E',
'Hm I2',
'Hm H',
'Hm E',
]
Result:
>>> for i in sorted(cols, key=k):
... print(i)
...
Hm I1
Aw I1
Hm I2
Aw I2
Hm R
Aw R
Hm H
Aw H
Hm E
Aw E
When sorting tuple
s, the first elements are compared first. If they're the same, the tuple
s are sorted by their second elements, and so on. This is similar to the way ordinary words are sorted alphabetically.
Since we first want all the elements with 'I'
together, then 'R'
, and so on, we'll put that first. To do that, we define a dictionary that gives each letter its desired priority. When we look up that letter (the fourth character in the string, s[3]
) in that dictionary, there's the first part of the key.
Next, we want the number after that letter. For this, we'll use some short-circuiting to get either the fifth character and onward (s[4:]
), or, if there aren't any, a 0
. We send that to int
, which will evaluate the number as a number to put '2'
after '12'
like it should be.
Finally, if the first two parts are the same, items will be sorted based on their first character. If this was a simpler sort we could just specify reverse=True
. If this part was a number, we could just take its negative. We'll just turn that character into a number with ord()
and then take the negative of that.
The result is keys of, for example, (0, 2, -65)
for 'Aw I2'
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With