I have a list of strings for which I would like to perform a natural alphabetical sort.
For instance, the following list is naturally sorted (what I want):
['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13']
And here's the "sorted" version of the above list (what I get using sorted()
):
['Elm11', 'Elm12', 'Elm2', 'elm0', 'elm1', 'elm10', 'elm13', 'elm9']
I'm looking for a sort function which behaves like the first one.
The sorted() built-in function allows us to sort the data. It accepts an iterable and returns a sorted list containing the items from the iterable. By default, it sorts in ascending order. (required) Iterable to sort like string, list, dictionary, tuple etc.
sorted() Return Value The sorted() function returns a sorted list.
Python in its language offers a sort function to perform this task. But due to fact that not all the containers in Python are mutable, such as string, the sort function doesn't work as it is in place tries to sort and immutability stops this.
Python uses an algorithm called Timsort: Timsort is a hybrid sorting algorithm, derived from merge sort and insertion sort, designed to perform well on many kinds of real-world data. It was invented by Tim Peters in 2002 for use in the Python programming language.
There is a third party library for this on PyPI called natsort (full disclosure, I am the package's author). For your case, you can do either of the following:
>>> from natsort import natsorted, ns >>> x = ['Elm11', 'Elm12', 'Elm2', 'elm0', 'elm1', 'elm10', 'elm13', 'elm9'] >>> natsorted(x, key=lambda y: y.lower()) ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13'] >>> natsorted(x, alg=ns.IGNORECASE) # or alg=ns.IC ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13']
You should note that natsort
uses a general algorithm so it should work for just about any input that you throw at it. If you want more details on why you might choose a library to do this rather than rolling your own function, check out the natsort
documentation's How It Works page, in particular the Special Cases Everywhere! section.
If you need a sorting key instead of a sorting function, use either of the below formulas.
>>> from natsort import natsort_keygen, ns >>> l1 = ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13'] >>> l2 = l1[:] >>> natsort_key1 = natsort_keygen(key=lambda y: y.lower()) >>> l1.sort(key=natsort_key1) >>> l1 ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13'] >>> natsort_key2 = natsort_keygen(alg=ns.IGNORECASE) >>> l2.sort(key=natsort_key2) >>> l2 ['elm0', 'elm1', 'Elm2', 'elm9', 'elm10', 'Elm11', 'Elm12', 'elm13']
Update November 2020
Given that a popular request/question is "how to sort like Windows Explorer?" (or whatever is your operating system's file system browser), as of natsort
version 7.1.0 there is a function called os_sorted
to do exactly this. On Windows, it will sort in the same order as Windows Explorer, and on other operating systems it should sort like whatever is the local file system browser.
>>> from natsort import os_sorted >>> os_sorted(list_of_paths) # your paths sorted like your file system browser
For those needing a sort key, you can use os_sort_keygen
(or os_sort_key
if you just need the defaults).
Caveat - Please read the API documentation for this function before you use to understand the limitations and how to get best results.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With