I want to find a way to sort strings that have numbers in them by their numerical size.
I found one way to sort strings that contain only numbers, which works well (Sorting numbers in string format with Python) but not when the string is a mix of words and numbers.
In this example I am creating the list in the order that I want, but the sorted() ruins it.
>>> s = ['A_10x05', 'A_10x50', 'A_10x100']
>>> print(sorted(s))
['A_10x05', 'A_10x100', 'A_10x50']
I am thinking I would need to split the string by numbers and sort each part, and I can sort the number parts using the solution above. Then where there are multiple strings that start the same way i.e section[i] = ('A_')
I sort section[i 1] and work my way to the end. This feels very complicated though, so maybe there is a better way.
Edit: The data could be any mix of words and numbers. It could 'A_10x05', or it could be 'Item_A_10x05x200_Base_01'. So the solution has to be general.
CodePudding user response:
IIUC, you are trying to multiply the numbers in 10x05
- which you can do by passing a key
function to sorted
def eval_result(s):
prefix, op = s.split('_')
num1, num2 = map(int, op.split('x'))
return num1 * num2
sorted(s, key=eval_result)
Output
['A_10x05', 'A_10x50', 'A_10x100']
CodePudding user response:
I believe what you want is just to sort each part of the input strings separately - text parts alphabetically, numeric parts by numeric value, with no multiplications involved. If this is the case you will need a helper function:
from re import findall
s = ['A_10x5', 'Item_A_10x05x200_Base_01', 'A_10x100', 'B']
def fun(s):
f = findall(r'\d |[A-Za-z_] ',s)
return list(map(lambda x:int(x) if x.isdigit() else x, f))
sorted(s, key = fun)
['A_10x5', 'A_10x100', 'B', 'Item_A_10x05x200_Base_01']