I have a list containing 6 strings:
s1 = 'foo[2]_bar'
s2 = 'foo[2]_ant'
s3 = 'foo[1]_bar'
s4 = 'foo[1]_ant'
s5 = 'foo[10]_bar'
s6 = 'foo[10]_ant'
str_arr = [s1, s2, s3, s4, s5, s6]
If I use str_arr.sort()
the order comes out like this:
foo[10]_ant
foo[10]_bar
foo[1]_ant
foo[1]_bar
foo[2]_ant
foo[2]_bar
However, I need the order to take more precedence of alphabetical sorting, meaning "ant"
should come before "bar"
in all cases, but also sub-sorting for numerical order.
So I need the output to be like this but I don't know how to accomplish this:
foo[1]_ant
foo[2]_ant
foo[10]_ant
foo[1]_bar
foo[2]_bar
foo[10]_bar
I'm not sure if there's some sort of filter or lambda function I can use but I can barely understand a lot of lambda functions I see on here.
CodePudding user response:
make a custom sort function and then pass it as a key
You can return multiple objects from your custom sort function and priority will be given on the basis of order of the returning.
s1 = 'foo[2]_bar'
s2 = 'foo[2]_ant'
s3 = 'foo[1]_bar'
s4 = 'foo[1]_ant'
s5 = 'foo[10]_bar'
s6 = 'foo[10]_ant'
str_arr = [s1, s2, s3, s4, s5, s6]
def custom_sort(x):
last_str = x.split("_")[-1]
num = x[x.index("[") 1: x.index("]")]
return last_str, int(num)
for i in (sorted(str_arr, key=custom_sort)):
print(i)
CodePudding user response:
Use a lambda
with multiple conditions. The conditions are prioritized from left-to-right:
Code:
s1 = 'foo[2]_bar'
s2 = 'foo[2]_ant'
s3 = 'foo[1]_bar'
s4 = 'foo[1]_ant'
s5 = 'foo[10]_bar'
s6 = 'foo[10]_ant'
str_arr = [s1, s2, s3, s4, s5, s6]
str_arr.sort(key=lambda x: (x[x.find("_") 1], int(x[x.find("[") 1:x.find("]")])))
print(str_arr)
Output:
['foo[1]_ant', 'foo[2]_ant', 'foo[10]_ant', 'foo[1]_bar', 'foo[2]_bar', 'foo[10]_bar']
How it works:
(For every entry x
)
From left-to-right we have the conditions:
x[x.find("_") 1:]
This is the first sorting condition. It will sort based on the word that comes after the underscore. Here, we slice the string by finding the underscore, and returning the portion of the string that occurs after it.int(x[x.find("[") 1:x.find("]")])
This is the second sorting condition. It will sort based on theint
between the[]
in the string. It slices the string so we are left with only that number, then it converts that number to anint
, and compares theint
to the integers in the other strings.
As stated above, using a lambda
with multiple conditions means it will prioritize the sorting conditions from left-to-right. Here, we prioritize sorting by the last word (so ant
always comes before bar
), and then sorting by the integer (so 1...ant comes before 2...ant and so on.