13

I'm trying to display some results in a human-readable way. For the purposes of this question, some of them are numbers, some are letters, some are a combination of the two.

I'm trying to figure out how I could get them to sort like this:

input = ['1', '10', '2', '0', '3', 'Hello', '100', 'Allowance']
sorted_input = sorted(input)
print(sorted_input)

Desired Results:

['0', '1', '2', '3', '10', '100', 'Allowance', 'Hello']

Actual results:

['0', '1', '10', '100', '2', '3', 'Allowance', 'Hello']

I'm having trouble coming up with how to do this.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
user2923558
  • 133
  • 5
  • 2
    possible duplicate of [Does Python have a built in function for string natural sort?](http://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort) – Steve Jessop Oct 27 '13 at 23:20

5 Answers5

15

1 - Install natsort module

pip install natsort

2 - Import natsorted

>>> input = ['1', '10', '2', '0', '3', 'Hello', '100', 'Allowance']

>>> from natsort import natsorted
>>> natsorted(input)
['0', '1', '2', '3', '10', '100', 'Allowance', 'Hello']

Source: https://pypi.python.org/pypi/natsort

Mingyu
  • 31,751
  • 14
  • 55
  • 60
3

I have found the code in the following link about natural sorting order very useful in the past:

http://www.codinghorror.com/blog/2007/12/sorting-for-humans-natural-sort-order.html

Ben
  • 6,687
  • 2
  • 33
  • 46
  • This was really useful towards understanding how it works, I was torn between marking this and Mingyu's, I ended up going with Mingyu's since it actually has a usable solution, but this was a great read. – user2923558 Oct 27 '13 at 23:37
1

This will do it. For purposes of comparison, it converts strings that can be converted to an integer to that integer, and leaves other strings alone:

def key(s):
    try:
        return int(s)
    except ValueError:
        return s

sorted_input = sorted(input, key=key)
Tim Peters
  • 67,464
  • 13
  • 126
  • 132
0

For your specific case:

def mySort(l):
    numbers = []
    words = []
    for e in l:
        try:
            numbers.append(int(e))
        except:
            words.append(e)
    return [str(i) for i in sorted(numbers)] + sorted(words)

print mySort(input)
JadedTuna
  • 1,783
  • 2
  • 18
  • 32
Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
0

You could split up the list, sort, then put it back together. Try something like this:

numbers = sorted(int(i) for i in input_ if i.isdigit())
nonnums = sorted(i for i in input_ if not i.isdigit())
sorted_input = [str(i) for i in numbers] + nonnums

You'll have to do something more complicated than isdigit if you can have non-integers.

If this doesn't cover your "some are a combination of the two," please elaborate what that means and what output you expect from them.

(Not tested, but should convey the idea.)

jpmc26
  • 28,463
  • 14
  • 94
  • 146