Sorting hybrid lists in Python
Question: Say I have this list `l = ['the fountainhead','atlas shrugged', 1, 67, 12, 0]`
which I want to sort so that the final result be `['atlas shrugged', 'the
fountainhead', 0, 1, 12, 67]`. This means that strings and integers in the
list should be both sorted in ascending order. If I use `sorted()` the digits
appear first:

    
    
    >>> sorted(l)
    [0, 1, 12, 67, 'atlas shrugged', 'the fountainhead']
    

and if I use lambda, it cannot get past ordering the list as it contains
incomparable elements of different type:

    
    
    >>> sorted(l, key=lambda x:int(x))
    
    Traceback (most recent call last):
      File "<pyshell#13>", line 1, in <module>
        sorted(l, key=lambda x:int(x))
      File "<pyshell#13>", line 1, in <lambda>
        sorted(l, key=lambda x:int(x))
    ValueError: invalid literal for int() with base 10: 'the fountainhead'
    

As far as I know, there is no way to utilize exception handling when working
with lambdas. This is just a simple example to illustrate the question. I'd
like to know if there is a general flexible way to sort hybrid lists in
Python. I have searched through relevant pages on SO but couldn't find a
general approach for this.


Answer: I think that the first problem here is that you have a hybrid list -- In
general, it becomes tricky to follow the code when you don't know what
operations you can do on which element since they aren't all the same type.

There is no general solution (since there is no _general_ way to know how to
compare objects of different types), but you can definitely handle the case
you have (if you must)...

    
    
    import numbers
    sorted(l, key=lambda x: (isinstance(x, numbers.Number), x))
    

should do the trick. Basically, my key function returns a `tuple`. Since
`tuple` (and all python sequences) are sorted lexicographically, python will
first look at the first element of the tuple -- In this case, it will be
`False` (`0`) if the item isn't a number so those elements will appear first.

Demo:

    
    
    >>> l = [1, 2, 3, 'foo', 'bar', 4, 8, -10, 'baz']
    >>> import numbers
    >>> sorted(l, key=lambda x: (isinstance(x, numbers.Number), x))
    ['bar', 'baz', 'foo', -10, 1, 2, 3, 4, 8]
    

