Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Natural Sort of list containing paths in Python

I have a list paths_list which contains the path of files(images) of a particular folder . Example:

['/home/username/images/s1/4.jpg', '/home/username/images/s1/7.jpg', 
'/home/username/images/s1/6.jpg', '/home/username/images/s1/3.jpg', 
'/home/username/images/s1/5.jpg', '/home/username/images/s1/10.jpg', 
'/home/username/images/s1/9.jpg', '/home/username/images/s1/1.jpg', 
'/home/username/images/s1/2.jpg', '/home/username/images/s1/12.jpg', 
'/home/username/images/s1/11.jpg', '/home/username/images/s1/8.jpg']

I want to sort then in the order: [/1.jpg ,2.jpg .....,/12.jpg] Neither sorting via length nor via alphabetical order is helping. What should be done here?

like image 811
Kancha Avatar asked Jun 23 '17 12:06

Kancha


People also ask

How do I sort the path of a file in Python?

You can use sorted with a lambda . For the sorting criteria, you can use os to first pull just the file name (using basename ), then you can split off just the filename less the extension (using splitext ). Lastly convert to int so you sort numerically instead of lexicographically.

How do you sort a list containing strings?

In Python, there are two ways, sort() and sorted() , to sort lists ( list ) in ascending or descending order. If you want to sort strings ( str ) or tuples ( tuple ), use sorted() .


2 Answers

You can use sorted with a lambda. For the sorting criteria, you can use os to first pull just the file name (using basename), then you can split off just the filename less the extension (using splitext).

Lastly convert to int so you sort numerically instead of lexicographically.

>>> import os
>>> l = ['/home/username/images/s1/4.jpg', '/home/username/images/s1/7.jpg', '/home/username/images/s1/6.jpg', '/home/username/images/s1/3.jpg', '/home/username/images/s1/5.jpg', '/home/username/images/s1/10.jpg', '/home/username/images/s1/9.jpg', '/home/username/images/s1/1.jpg', '/home/username/images/s1/2.jpg', '/home/username/images/s1/12.jpg', '/home/username/images/s1/11.jpg', '/home/username/images/s1/8.jpg']
>>> sorted(l, key=lambda i: int(os.path.splitext(os.path.basename(i))[0]))
['/home/username/images/s1/1.jpg',
 '/home/username/images/s1/2.jpg',
 '/home/username/images/s1/3.jpg',
 '/home/username/images/s1/4.jpg',
 '/home/username/images/s1/5.jpg',
 '/home/username/images/s1/6.jpg',
 '/home/username/images/s1/7.jpg',
 '/home/username/images/s1/8.jpg',
 '/home/username/images/s1/9.jpg',
 '/home/username/images/s1/10.jpg',
 '/home/username/images/s1/11.jpg',
 '/home/username/images/s1/12.jpg']
like image 186
Cory Kramer Avatar answered Sep 30 '22 04:09

Cory Kramer


Use natural sorting (see this question): clean code and good practice when sorting strings.

from natsort import natsorted
l = ['/home/username/images/s1/4.jpg', '/home/username/images/s1/7.jpg', '/home/username/images/s1/6.jpg', '/home/username/images/s1/3.jpg', '/home/username/images/s1/5.jpg', '/home/username/images/s1/10.jpg', '/home/username/images/s1/9.jpg', '/home/username/images/s1/1.jpg', '/home/username/images/s1/2.jpg', '/home/username/images/s1/12.jpg', '/home/username/images/s1/11.jpg', '/home/username/images/s1/8.jpg']
natsorted(l)

gives

['/home/username/images/s1/1.jpg',
'/home/username/images/s1/2.jpg',
'/home/username/images/s1/3.jpg',
'/home/username/images/s1/4.jpg',
'/home/username/images/s1/5.jpg',
'/home/username/images/s1/6.jpg',
'/home/username/images/s1/7.jpg',
'/home/username/images/s1/8.jpg',
'/home/username/images/s1/9.jpg',
'/home/username/images/s1/10.jpg',
'/home/username/images/s1/11.jpg',
'/home/username/images/s1/12.jpg']

Natural sorting sorts based on how you would read things on a computer screen (alphabetically and numerically), rather than how the computer reads the code.

like image 26
VinceP Avatar answered Sep 30 '22 04:09

VinceP