user1083734
user1083734

Reputation: 5185

What is the best way to sort this list?

I have the following list:

my_list = ['name.13','name.1', 'name.2','name.4', 'name.32']

And I would like sort the list and print it out in order, like this

name.1
name.2
name.4
name.13
name.32

What I have tried so far is:

print sorted(my_list)

name.1
name.13
name.2
name.32
name.4

The sorted() command obviously treats the string alphabetically. Maybe it would be better to sort numerically after detecting the . first?

Is there an good way to sort it properly? What would be the most efficient approach to take? How would I apply this is I had a list of tuples and wanted to sort it using the second elemnt of the tuples? For instance:

tuple_list = [('i','name.2'),('t','name.13'),('s','name.32'),('l','name.1'),('s','name.4')]

print tuple_list
'l','name.1'
'i','name.2'
's','name.4'
't','name.13'
's','name.32'

Thanks for your help and, as always, comment if you think the question can be improved/clarified.

Alex

Upvotes: 2

Views: 287

Answers (4)

SethMMorton
SethMMorton

Reputation: 48725

UPDATED ANSWER

As of natsort version 4.0.0, this works out of the box without having to specify any options:

>>> import natsort
>>> my_list = ['name.13','name.1', 'name.2','name.4', 'name.32']
>>> natsort.natsorted(my_list)
['name.1','name.2', 'name.4','name.13', 'name.32']

OLD ANSWER for natsort < 4.0.0

If you do not object to external packages, try the natsort package (version >= 3.0.0):

>>> import natsort
>>> my_list = ['name.13','name.1', 'name.2','name.4', 'name.32']
>>> natsort.natsorted(my_list, number_type=int)
['name.1','name.2', 'name.4','name.13', 'name.32']

The number_type argument is necessary in this case because natsort by default looks for floats, and the decimal point would make all these numbers be interpreted as floats.


Full disclosure: I am the natsort author.

Upvotes: 4

perreal
perreal

Reputation: 97948

This one uses more memory but does not split each item multiple times:

from operator import itemgetter
my_list = ['name.13','name.1', 'name.2','name.4', 'name.32']
my_nlist= [ (int(n.split('.')[1]), i) for i,n in enumerate(my_list)]
my_list = [ my_list[t[1]] for t in sorted(my_nlist, key=itemgetter(0))]

to deal with tuples:

my_list = [('i','name.2'),('t','name.13'),
           ('s','name.32'),('l','name.1'),('s','name.4')]
my_nlist= [ (int(n[1].split('.')[1]), i) for i,n in enumerate(my_list)]
my_list = [ my_list[t[1]] for t in sorted(my_nlist, key=itemgetter(0))]

Upvotes: 3

jeyk
jeyk

Reputation: 443

You could try it similarly to this answer:

>>> my_list = ['name.13','name.1', 'name.2','name.4', 'name.32']
>>> sorted(my_list, key=lambda a: (int(a.split('.')[1])))
['name.1', 'name.2', 'name.4', 'name.13', 'name.32']

Or with tuples:

>>> tuple_list = [('i','name.2'),('t','name.13'),('s','name.32'),('l','name.1'),('s','name.4')]
>>> sorted(tuple_list, key=lambda (a,b): (int(b.split('.')[1])))
[('l', 'name.1'), ('i', 'name.2'), ('s', 'name.4'), ('t', 'name.13'), ('s', 'name.32')]

Edit to explain what this does:

The example passes a lambda function to sorted that splits the strings and then converts the second part to an integer. sorted then uses this integer to sort the list items.

This example completely ignores the strings to the left of the dot when sorting. Please let me know if you also need to sort by the first part.

Upvotes: 8

karthikr
karthikr

Reputation: 99620

Try this:

sorted(my_list, key=lambda x: int(x.split('.')[1]))

Demo:

>>> my_list = ['name.13','name.1', 'name.2','name.4', 'name.32']
>>> sorted(my_list, key=lambda x: int(x.split('.')[1]))
['name.1', 'name.2', 'name.4', 'name.13', 'name.32']
>>> 

Extending it to the tuple,

sorted(tuple_list, key = lambda x: int(x[1].split('.')[1]))

DEMO:

>>> sorted(tuple_list, key = lambda x: int(x[1].split('.')[1]))
[('l', 'name.1'), ('i', 'name.2'), ('s', 'name.4'), ('t', 'name.13'), ('s', 'name.32')]

Upvotes: 3

Related Questions