14

I have a list that consists of details like this:

list1 = ["1", "100A", "342B", "2C", "132", "36", "302F"]

I want to sort this list, such that the values are in the following order:

list1 = ["1", "2C", "36", "100A", "132", "302F", "342B"]

Just doing list1.sort() obviously doesn't give the correct answer - it gives:

list1 = ["1", "100A", "132", "2C", "36", "302F", "342B"]

I'm assuming this is because Python treats all these as strings directly. However, I want to sort them based on their numeric value FIRST, and then the character that follows the number.

How do I proceed?

Tomerikoo
  • 18,379
  • 16
  • 47
  • 61
Randomly Named User
  • 1,889
  • 7
  • 27
  • 47
  • See this post (http://stackoverflow.com/questions/11850425/custom-python-list-sorting) and define a custom compare function. – lurker Oct 14 '13 at 18:18
  • 2
    This is called **natural sort**. 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) – Ashwini Chaudhary Oct 14 '13 at 18:18

2 Answers2

29

You want to use natural sort:

import re

_nsre = re.compile('([0-9]+)')
def natural_sort_key(s):
    return [int(text) if text.isdigit() else text.lower()
            for text in re.split(_nsre, s)]   

Example usage:

>>> list1 = ["1", "100A", "342B", "2C", "132", "36", "302F"]
>>> list1.sort(key=natural_sort_key)
>>> list1
['1', '2C', '36', '100A', '132', '302F', '342B']

This functions by splitting the elements into lists separating out the numbers and comparing them as integers instead of strings:

>>> natural_sort_key("100A")
['', 100, 'a']
>>> natural_sort_key("342B")
['', 342, 'b']

Note that this only works in Python3 if you are always comparing ints with ints and strings with strings, otherwise you get a TypeError: unorderable types exception.

Claudiu
  • 224,032
  • 165
  • 485
  • 680
0

Well, you have to find a way to convert your strings to numbers first. For example

import re
def convert(str):
    return int("".join(re.findall("\d*", str)))

and then you use it as a sort key:

list1.sort(key=convert)
freakish
  • 54,167
  • 9
  • 132
  • 169
  • There are some more natural sort solutions here: http://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort – nofinator Oct 14 '13 at 18:30