Reputation: 3
I have been asked to define a function that sorts a list based on file extension..
I understand sorting, but I don't understand how to start the sort from the "." character.
I want the following result:
>>> extsort(['a.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt', 'x.c'])
['a.c', 'x.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt']
Upvotes: 0
Views: 1213
Reputation: 17263
You can pass key function as a parameter for sorted
:
>>> l = ['a.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt', 'x.c']
>>> sorted(l, key=lambda x: splitext('.')[1])
['a.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt', 'x.c']
If you need the files to with same extension to be sorted by their name you can change key function to reverse the split result:
>>> l = ['x.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt', 'a.c']
>>> sorted(l, key=lambda x: splitext(x)[::-1])
['a.c', 'x.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt']
Upvotes: 4
Reputation: 155363
For a solution that works even if some of the files don't have extensions (and is somewhat more self-documenting), use os.path.splitext
as part of sorted
's key
function. When there is no file extension, it will treat the extension as the empty string, ''
, sorting it before all other extensions:
>>> l = ['b.py', 'a.c', 'a.py', 'bar.txt', 'foo.txt', 'x.c', 'foo']
>>> sorted(l, key=lambda x: os.path.splitext(x)[1])
['foo', 'a.c', 'x.c', 'b.py', 'a.py', 'bar.txt', 'foo.txt']
Note that b.py
sorted before a.py
here, because it appeared first in the input, and the sort only keyed on the file extension. To make it sort by extension, then full name, key on a tuple of the extension followed by the non-extension name (easily done by slicing os.path.splitext
's return value using [::-1]
which reverses the order of the elements returned), so a.py
precedes b.py
regardless of where they appeared in the input:
>>> sorted(l, key=lambda x: os.path.splitext(x)[::-1])
['foo', 'a.c', 'x.c', 'a.py', 'b.py', 'bar.txt', 'foo.txt']
Upvotes: 3