Home > database >  python convert strings to int and order list by string first in descending, integer in ascending?
python convert strings to int and order list by string first in descending, integer in ascending?

Time:08-24

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]
  • Related