If you want your code to be almost two times faster, you can use a lookup table, I've used a one liner for this, but it can also be split up. I'm printing this to provide insight in what this object looks like. For the numbers I can make a list directly, for the letters I'll use a more compact notation.
decode = {character: index for index, character in enumerate([chr(i) for i in range(ord("A"), ord("Z") + 1)] + ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"])}
print(decode)
s = "8 G J 4 5 D"
print(*sorted(s.split(), key=lambda c: (c.isdecimal(), c)))
print(*sorted(s.split(), key = lambda c: decode[c]))
from timeit import repeat
loops = 500_000
count = 1
print(loops * min(repeat("sorted(s.split(), key=lambda c: (c.isdecimal(), c))", globals=globals(), repeat=loops, number=count)))
print(loops * min(repeat("sorted(s.split(), key = lambda c: decode[c])", globals=globals(), repeat=loops, number=count)))
Output:
{'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7, 'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15, 'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23, 'Y': 24, 'Z': 25, '0': 26, '1': 27, '2': 28, '3': 29, '4': 30, '5': 31, '6': 32, '7': 33, '8': 34, '9': 35}
D G J 4 5 8
D G J 4 5 8
3.6460114642977715
2.3174798116087914
More ideas?