-2

Is there a simple way to do a "Filing cabinet" sort of strings containing both alpha and numeric characters?

I.e. a list such as:

[aa2, ab2, bb1, bc1, ab3, aa3, ba2, ba1, aa1, ac1, bb2, bb3, ab1]

is sorted to

[aa1, aa2, aa3, ab1, ab2, ab3, ac1, ba1, ba2, bb1, bb2, bb3, bc1]

I have an idea for a script that dissects them into individual characters, sorts each set, and then reassembles them, but that seems like the hard way. :-)


Here si the final code that works well. Thanks pepr from Experts Exchange D0t k0m and to jamylak for answering before the questions was killed. The built in sorts cannot handle the numerical portion of the sort. I.e. they sort the numerical as lexical...

[aa1, aa11, aa111, aa2, aa3, ba1, ba11, ba2]

... instead of ...

[aa1, aa2, aa3, aa11, aa111, ba1, ba2, ba11]

So this variation of jamylak's code works beautifully ...

def lexinumericalsort(_list):
    def _key(item):
        # pattern will split strings and letters up to 8 times (intended for device file names)
        pattern = ('([a-zA-Z]{0,})(\d{0,})') * 8 
        try:
            result = re.match(pattern, item).groups()
            result = list(result)
            for no, val in enumerate(result):
                if val is '':
                    result.pop(no) # Remove blanks
                try:
                    # Convert to integer if possible
                    result[no] = int(result[no]) 
                except ValueError, e:
                    pass #silence if fails (leaves as character)
            return result
        except AttributeError, e:
            e = ("functions.lexinumericalsort:\n" + 
                 "Unable to resolve list into pattern matched groups.\n" +
                 str(e))
            print e
            return None

    return sorted(_list, key = _key)
RightmireM
  • 2,381
  • 2
  • 24
  • 42
  • Have you tried using the `sorted` function? or equivalently the `.sort()` method to sort your original list – jamylak May 07 '13 at 11:18
  • When you have to insert extra paragraphs to get past a quality filter, perhaps it is time to improve the quality of the question itself? You could have used code formatting, for example. Or left out the 'best wishes' part, and the 'I have a question'. – Martijn Pieters May 07 '13 at 11:20
  • perhaps you are talking about the second example mentioned in my question? – jamylak May 07 '13 at 11:35
  • Possibly related: http://stackoverflow.com/questions/4836710/does-python-have-a-built-in-function-for-string-natural-sort – Aya May 07 '13 at 11:37

1 Answers1

1
>>> sorted("aa2, ab2, bb1, bc1, ab3, aa3, ba2, ba1, aa1, ac1, bb2, bb3, ab1".split(', '))
['aa1', 'aa2', 'aa3', 'ab1', 'ab2', 'ab3', 'ac1', 'ba1', 'ba2', 'bb1', 'bb2', 'bb3', 'bc1']

Although maybe you mean this:

>>> items = ['a11', 'a2']
>>> sorted(items)
['a11', 'a2']

where sorted doesn't work. Just use a regex pattern to match your data and pass a key function to sorted

>>> import re
>>> def key(item):
        g = re.match(r'([a-zA-Z]+)(\d+)', item).groups()
        return g[0], int(g[1])

>>> sorted(items, key=key)
['a2', 'a11']
jamylak
  • 128,818
  • 30
  • 231
  • 230