I've got a list that looks like this:
["A", "X", "B", "3", "5", "1"]
I'm trying to find a way to sort this so it looks like this:
["X", "B", "A", 1, 3, 5]
I created a small function to convert the list strings to integer where appropriate:
def convert_list(list_to_convert: list) -> list:
"""If a list contains strings where some should be ints, this attempts to
convert them to ints where appropriate"""
converted_list = []
for item in list_to_convert:
try:
item = int(item)
except ValueError:
pass
converted_list.append(item)
return converted_list
That gives me ["A", "X", "B", 3, 5, 1]
But I'm not sure how to get this list to sort by the letters in descending, while sorting the integers in ascending.
I've tried this:
sorted_int_grade_list = sorted(
ordered_grade_list, key=lambda i: (isinstance(i, int), i)
)
But that gives me ["A", "B", "X", 1, 3, 5]
(alpha is wrong direction, integers are correct)
I'm not sure how to sort this in two different fashions - any ideas would be helpful.
CodePudding user response:
You can first separate them into two lists, sort each of them, and then merge them:
lst = ["A", "X", "B", "3", "5", "1"]
letters = []
numbers = []
for x in lst:
try:
numbers.append(int(x))
except ValueError:
letters.append(x)
output = [*sorted(letters, reverse=True), *sorted(numbers)] # uses generalized unpacking: PEP 448
print(output) # ['X', 'B', 'A', 1, 3, 5]
CodePudding user response:
Here's an example sort func that'd do what you'd want
def alphanum_sortfunc(alphanum):
is_int = isinstance(alphanum, int)
# ints in ascending, strings in descending
order_key = alphanum if is_int else -ord(alphanum)
# tuple-based sorting, sort first by is_int, then by order_key
return (is_int, order_key)
Which you would use like:
sorted(["A", "X", "B", 3, 5, 1], key=alphanum_sortfunc)
#=> ['X', 'B', 'A', 1, 3, 5]
CodePudding user response:
You can create a lookup table:
import string
lu={c:i for i,c in enumerate(string.ascii_uppercase[::-1] string.digits)}
# {'Z': 0, 'Y': 1, 'X': 2, 'W': 3, 'V': 4, 'U': 5, 'T': 6, 'S': 7, 'R': 8, 'Q': 9, 'P': 10, 'O': 11, 'N': 12, 'M': 13, 'L': 14, 'K': 15, 'J': 16, 'I': 17, 'H': 18, 'G': 19, 'F': 20, 'E': 21, 'D': 22, 'C': 23, 'B': 24, 'A': 25, '0': 26, '1': 27, '2': 28, '3': 29, '4': 30, '5': 31, '6': 32, '7': 33, '8': 34, '9': 35}
Then sort based on that:
li=["A", "X", "B", "3", "5", "1"]
>>> sorted(li, key=lambda e: lu.get(e,-1))
['X', 'B', 'A', '1', '3', '5']
Alternatively, you can write a lambda to reverse if a digit and normal order if an int:
>>> sorted(li, key=lambda e: int(e) if e.isdigit() else -ord(e))
['X', 'B', 'A', '1', '3', '5']
Then in either case, convert the digits to ints:
>>> [int(x) if x.isdigit() else x for x in sorted(li, key=lambda e: lu.get(e,-1))]
['X', 'B', 'A', 1, 3, 5]