saturngod
saturngod

Reputation: 24949

Python Sorted By Name

I tried to sort using sorted

dir =["A1","A2","A10","A3"]
sorted(dir)

My expected array is

["A1","A2","A3","A10"]

but actual result is

["A1", "A10", "A2", "A3"]

How to sort array by name in python ?

Upvotes: 2

Views: 5582

Answers (2)

Thomas Guyot-Sionnest
Thomas Guyot-Sionnest

Reputation: 2510

To extend this question, I had to sort interface names in a natural way. What makes it a bit more complex is interfaces can go in many flavors... You have the traditional ones such as lo, eth0, etc... and some more advanced schemes like enp4s0f1d1. The solution is to split them based on type, convert numbers to int's and care must be taken to ensure comparison happens on same type.

So I came up with this sort function which should be fairly bulletproof (as long as you give it strings...)

def ethkey(eth):
    """Split an ethernet device name between text and digit groups as int,
    allowing consistent sorting of interfaces.

    Usage: `sorted(if_list, key=ethkey)`

    :param eth: Value to sort
    :type eth: str
    :return: List of str's (even indexes) and int's (odd indexes) to compare
    :rtype: list
    """

    keys = []
    if not eth:
        # If eth is a string it's empty, just return blank list
        return keys

    # Start with the first character already in last
    last, eth = eth[0], eth[1:]
    # If last is int we start at offset 1
    if last.isdigit():
        keys.append('')

    for i in eth:
        if i.isdigit() is last.isdigit():
            # Keep accumulating same type chars
            last += i
        else:
            # Save and restart next round
            keys.append(int(last) if last.isdigit() else last)
            last = i

    # Save final round and return
    keys.append(int(last) if last.isdigit() else last)
    return keys

It can then be used as such:

sorted(int_list, key=ethkey)

Upvotes: 0

Matthew Adams
Matthew Adams

Reputation: 10156

It is sorting by alphabetical order, so you need to break up the numbers and convert them to ints and sort with that. (Numbers in strings are treated as just characters, so it "sees" "A10" and tries to sort it first by "A", then by "1", and then by "0.") For example:

>>> sorted(dir, key=lambda x: int(x[1:]))
['A1', 'A2', 'A3', 'A10']

If you are going to have other letters besides "A" in dir, you'll need a more complicated sorting method, but it will be something along the same lines. (If you explain what dir contains more, I can write an example for that.) As mgilson's comment points out, if the elements of dir follow the 1 char + number format, then you could take advantage of tuple sorting and do something like this:

>>> dir.append('B12')
>>> sorted(dir, key=lambda x: (x[0],int(x[1:])))
['A1', 'A2', 'A3', 'A10', 'B12']

Upvotes: 6

Related Questions