0

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.

3 Answers 3

7

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]
Sign up to request clarification or add additional context in comments.

Comments

3

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]

Comments

2

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]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.