I'm trying to sort a list with numbers and letter by numeric value.
list = ['3a', '13a', '5a', '11a']
When I use the .sort function it sorts it like this:
['11a', '13a', '3a', '5a']
Like it's only looking at the first number.
I'm trying to sort a list with numbers and letter by numeric value.
list = ['3a', '13a', '5a', '11a']
When I use the .sort function it sorts it like this:
['11a', '13a', '3a', '5a']
Like it's only looking at the first number.
If you just use an unmodified sorted
it will sort on the ASCII codes on each character in the string:
>>> sorted(['2','11','01000'])
['01000', '11', '2']
vs adding a key value that tells sorted
to use the integer value:
>>> sorted(['2','11','01000'], key=int)
['2', '11', '01000']
For strings that are a mixture of integers and letters, use a natural sort where letters are sorted lexicographically and numbers are treated to simple integer comparison:
import re
def natural_sort(l):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
return sorted(l, key = alphanum_key)
>>> li = ['3a', '13a', '5a', '11a']
>>> natural_sort(li)
['3a', '5a', '11a', '13a']
The advantage of this version is it handles multiple groups of numbers and letters:
>>> li = ['3a33', '3a2', '3b1', '3a1', '5a', '11a']
>>> natural_sort(li)
['3a1', '3a2', '3a33', '3b1', '5a', '11a']
As well as what you would expect with the letters in front:
>>> li = ['a33', 'a2', 'b1', 'a1', 'a', 'a00004']
>>> natural_sort(li)
['a', 'a1', 'a2', 'a00004', 'a33', 'b1']
(PS: Best to not call a python list list
because it stomps on the name of the function...)
You can pass in a lambda for a sorting key.
list = ['3a', '13a', '5a', '11a']
list.sort(key=lambda x: int(x[:-1]))
The important part is:
lambda x: int(x[:-1])
which takes in a string, removes the last character, and converts it to an integer.
Your list is a list of strings. So list.sort
will sort the elements lexicographically. You can change this by passing a key to your sorting function. You can use re.match
(import re
first) to extract the digits and compare. Something like this:
In [30]: list_ = ['3a', '13a', '5a', '11a']
In [31]: matcher = re.compile('\d+')
In [32]: sorted(list_, key=lambda x: int(matcher.match(x).group()))
Out[32]: ['3a', '5a', '11a', '13a']
This works best if your elements have something more than a
at the end of them.
There is package called natsort
from natsort import natsorted
LL = ['3a', '13a', '5a', '11a']
natsorted(LL)
Out[296]: ['3a', '5a', '11a', '13a']
@dawg's example using natsort
:
li = ['3a33', '3a2', '3a1', '13a', '5a', '11a']
natsorted(li)
Out[298]: ['3a1', '3a2', '3a33', '5a', '11a', '13a']