Is there a built in function for string natural sort?
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.
Natural sorting
Google: Python natural sorting.
Result 1: The page you linked to.
But don't stop there!
Result 2: Jeff Atwood's blog that explains how to do it properly.
Result 3: An answer I posted based on Jeff Atwood's blog.
Here's the code from that answer:
import re
def natural_sort(l):
convert = lambda text: int(text) if text.isdigit() else text.lower()
alphanum_key = lambda key: [convert(c) for c in re.split('([0-9]+)', key)]
return sorted(l, key=alphanum_key)
Results for your data:
PresserInc-1.jpg
PresserInc-1_10.jpg
PresserInc-1_11.jpg
PresserInc-2.jpg
PresserInc-3.jpg
etc...
See it working online: ideone
Natural sorting of a list in Python3
Your code is correct, but your data look incorrect: all the entries have a leading whitespace, which implies they are "before" the one you identify as least, that actually have no leading whitespace.
If the data is fine as they are I suggest you to revise the code to ignore leading whitespaces (check this: How do I remove leading whitespace in Python?).
How to natural sort string with multiple numbers in it
This should do the trick:
z = sorted(list_list, key=lambda s: (s[-5:-3], s[-2:]))
Sort list of string in Python
Solved.
from natsort import natsorted, ns
natsorted(listElements, alg=ns.IGNORECASE)
Python analog of PHP's natsort function (sort a list using a natural order algorithm)
From my answer to Natural Sorting algorithm:
import re
def natural_key(string_):
"""See https://blog.codinghorror.com/sorting-for-humans-natural-sort-order/"""
return [int(s) if s.isdigit() else s for s in re.split(r'(\d+)', string_)]
Example:
>>> L = ['image1.jpg', 'image15.jpg', 'image12.jpg', 'image3.jpg']
>>> sorted(L)
['image1.jpg', 'image12.jpg', 'image15.jpg', 'image3.jpg']
>>> sorted(L, key=natural_key)
['image1.jpg', 'image3.jpg', 'image12.jpg', 'image15.jpg']
To support Unicode strings, .isdecimal()
should be used instead of .isdigit()
. See example in @phihag's comment. Related: How to reveal Unicodes numeric value property.
.isdigit()
may also fail (return value that is not accepted by int()
) for a bytestring on Python 2 in some locales e.g., '\xb2' ('²') in cp1252 locale on Windows.
Natural sort order string comparison in Java - is one built in?
In java the "natural" order meaning is "lexicographical" order, so there is no implementation in the core like the one you're looking for.
There are open source implementations.
Here's one:
NaturalOrderComparator.java
Make sure you read the:
Cougaar Open Source License
I hope this helps!
Sorting a list of strings numerically
Yes:
flist.sort(key=lambda fname: int(fname.split('.')[0]))
Explanation: strings are lexically sorted so "10"
comes before "3"
(because "1"
< "3"
, so whatever comes after "1"
in the first string is ignored). So we use list.sort()
's key
argument which is a callback function that takes a list item and return the value to be used for ordering for this item - in your case, an integer built from the first part of the filename. This way the list is properly sorted on the numerical values.
Related Topics
Limiting Floats to Two Decimal Points
A Non-Blocking Read on a Subprocess.Pipe in Python
Why Dict.Get(Key) Instead of Dict[Key]
Difference Between Class and Instance Attributes
Passing HTML to Template Using Flask/Jinja2
Check If a Given Key Already Exists in a Dictionary
Packaging a Python Script on Linux into a Windows Executable
How to Get a Cron Like Scheduler in Python
How to Check If String Input Is a Number
How to Make Good Reproducible Pandas Examples
Error: Unable to Find Vcvarsall.Bat
What Does the 'B' Character Do in Front of a String Literal
How to Compare Floats For Almost-Equality in Python
Selenium Using Python - Geckodriver Executable Needs to Be in Path
What Does "Syntaxerror: Missing Parentheses in Call to 'Print'" Mean in Python
Find Size and Free Space of the Filesystem Containing a Given File