FAQ
I have a list...

['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.

## Search Discussions

•  at Apr 8, 2010 at 10:54 pm ⇧

On Thu, Apr 8, 2010 at 3:52 PM, Ben Racine wrote:
I have a list...

['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.
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
•  at Apr 8, 2010 at 10:59 pm ⇧

Ben Racine wrote:
I have a list...

['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.

L.sort(key=lambda s: int(s.split('_')[1]))

(Which is not necessarily elegant, but it is short.)

Gary Herron
•  at Apr 8, 2010 at 11:01 pm ⇧

On Apr 9, 12:52?am, Ben Racine wrote:
I have a list...

['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.
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
•  at Apr 8, 2010 at 11:58 pm ⇧

On Thu, Apr 8, 2010 at 4:01 PM, Joaquin Abian wrote:
On Apr 9, 12:52?am, Ben Racine wrote:
I have a list...

['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?
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']
At least conceptually, that's how list.sort() with a key= argument
works internally (i.e. via Schwartzian transform).

Cheers,
Chris
•  at Apr 9, 2010 at 1:21 pm ⇧

On Apr 9, 1:58?am, Chris Rebert wrote:
On Thu, Apr 8, 2010 at 4:01 PM, Joaquin Abian wrote:
On Apr 9, 12:52?am, Ben Racine wrote:
I have a list...
['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?
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']
At least conceptually, that's how list.sort() with a key= argument
works internally (i.e. via Schwartzian transform).

Cheers,
Chris
--http://blog.rebertia.com
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
•  at Apr 9, 2010 at 12:43 am ⇧

On 04/09/10 08:52, Ben Racine wrote:
I have a list...

['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.
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 Apr 9, 2010 at 4:19 pm ⇧

L.sort(key=lambda s: int(s.split('_')[1]))

(Which is not necessarily elegant, but it is short.)
I grant it a measure of elegance as well.
•  at Apr 10, 2010 at 11:31 am ⇧

Ben Racine <i3enhamin at gmail.com> writes:
I have a list...

['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?
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)
•  at Apr 10, 2010 at 2:51 pm ⇧

On Apr 9, 8:52?am, Ben Racine wrote:
I have a list...
['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?
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.
•  at Apr 10, 2010 at 3:04 pm ⇧

alex23 wrote:
On Apr 9, 8:52 am, Ben Racine wrote:
I have a list...
['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?
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.
•  at Apr 10, 2010 at 3:20 pm ⇧

MRAB wrote:
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.

## Related Discussions

Discussion Overview
 group python-list categories python posted Apr 8, '10 at 10:52p active Apr 10, '10 at 3:20p posts 12 users 9 website python.org

### 9 users in discussion

Content

People

Support

Translate

site design / logo © 2022 Grokbase