Sort filenames naturally with Qt

Viewed 15358

I am reading a directories content using QDir::entryList(). The filenames within are structured like this:

index_randomNumber.png

I need them sorted by index, the way the Windows Explorer would sort the files so that I get

0_0815.png
1_4711.png
2_2063.png
...

instead of what the sorting by QDir::Name gives me:

0_0815.png
10000_6661.png
10001_7401.png
...

Is there a built-in way in Qt to achieve this and if not, what's the right place to implement it?

6 Answers

This isn't an answer to the question as such, but some general information for the benefit of others that stumble across this trying to figure out how to "sort naturally".

First off: it's impossible. "Correct" natural sorting depends on context that — short of "true" artificial intelligence — is virtually impossible to have. For instance, if I have a bunch of file names with mixed numbers and letters, and some parts of those names happen to match [0-9a-f], is that a hexadecimal number? Is "1,500" the same as "1500", or are "1" and "500" individual numbers? Does "2019/06/07" come before or after "2019/07/06"? What about "1.21" vs. "1.5"? (Hint: the last depends on if those are decimal numbers or semantic version numbers.)

"Solving" this problem requires constraining it; deciding we're only going to handle specific cases, and anything outside of those bounds is just going to produce a "wrong" answer. (Fortunately, the OP's problem would appear to already satisfy the usual set of constraints.)

That said, I believe QCollator works generally well (again, in that it doesn't "really" work, but it succeeds within the constraints that are generally accepted). In the "own solutions" department, have a look also at qtNaturalSort, which I wrote as a Qt-API improvement over a different (not QCollator) algorithm. (Case insensitivity is not supported as of writing, but patches welcomed!) I put a whole bunch of effort into making it parse numbers "correctly", even handling numbers of arbitrary length and non-BMP digits.

Related