['dir_0_error.dat', 'dir_120_error.dat', 'dir_30_error.dat', 'dir_330_error.dat']
I want to sort it based upon the numerical value only.
Does someone have an elegant solution to this?
Thanks,
Ben R.
a = ['dir_0_error.dat', 'dir_120_error.dat', 'dir_30_error.dat',
'dir_330_error.dat']
def key(item):
return int(item.split('_')[1])
a.sort(key=key)
Cheers,
Chris
--
http://blog.rebertia.com
How about a one liner?
L.sort(key=lambda s: int(s.split('_')[1]))
(Which is not necessarily elegant, but it is short.)
Gary Herron
not sure about elegance, but my two cents:
>> mylist = ['dir_0_error.dat', 'dir_120_error.dat', 'dir_30_error.dat', 'dir_330_error.dat']
>> mylist = [(int(item.split('_')[1]), item) for item in mylist]
>> mylist.sort()
>> mylist = [item for idx, item in mylist]
>> mylist
['dir_0_error.dat', 'dir_30_error.dat', 'dir_120_error.dat',
'dir_330_error.dat']
joaquin
list.sort() and sorted() accept `key` argument, which receives a
callable that transform the item to be sorted into sorting key. So if
you have:
l = ['dir_30_error.dat', 'dir_120_error.dat',
'dir_330_error.dat', 'dir_0_error.dat']
# 'dir_0_error.dat' -> 0
# 'dir_30_error.dat' -> 30
def getnum(s):
return int(''.join(x for x in s if x.isdigit()))
# sort based on getnum()'s return value
l.sort(key=getnum)
At least conceptually, that's how list.sort() with a key= argument
works internally (i.e. via Schwartzian transform).
Chris, thanks for the comment. I did not know that name (Schwartzian
transform)
I knew it as the decorate-sort-undecorate strategy.
Now after learning that it was a Perl idiom I feel somewhat
embarrassed ;-)
BTW, I actually prefer the l.sort(key=f) method.
Just my lazy neurons were back to Python 2.3 when I wrote the
response.
Joaquin
I grant it a measure of elegance as well.
I use code like the hack below to sort miscellaneous strings that
consist of mixed numerical and non-numerical parts.
import re
nsk_re = re.compile("([0-9]+)|([^0-9]+)")
def numeric_sort_key(x):
return [handle_int_nonint(i_ni) for i_ni in nsk_re.findall(x)]
def handle_int_nonint(int_nonint_tuple):
if int_nonint_tuple[0]:
return int(int_nonint_tuple[0])
else:
return int_nonint_tuple[1]
def numerically_sorted(l):
return sorted(l, key=numeric_sort_key)
This approach doesn't rely on knowing the format of the string:
>>> from string import maketrans, letters, punctuation
>>> a = ['dir_0_error.dat', 'dir_120_error.dat', 'dir_30_error.dat', 'dir_330_error.dat']
>>> def only_numbers(s):
... nums = s.translate(None, letters+punctuation)
... return int(nums)
...
>>> a.sort(key=only_numbers)
>>> a
['dir_0_error.dat', 'dir_30_error.dat', 'dir_120_error.dat',
'dir_330_error.dat']
If you're using Python 3.x, the string module has been removed, so you
can find the maketrans function on str there.
The string module still exists in Python 3.x, but the string functions
which have been superseded by string methods have been removed.
Awesome, thanks for the heads up.