Anyone have a good resource or provide a sample of a natural order sort in C# for an FileInfo
array? I am implementing the IComparer
interface in my sorts.
相关问题
- Sorting 3 numbers without branching [closed]
- How to toggle on Order in ReactJS
- Graphics.DrawImage() - Throws out of memory except
- PHP Recursively File Folder Scan Sorted by Modific
- Why am I getting UnauthorizedAccessException on th
Let me explain my problem and how i was able to solve it.
Problem:- Sort files based on FileName from FileInfo objects which are retrieved from a Directory.
Solution:- I selected the file names from FileInfo and trimed the ".png" part of the file name. Now, just do List.Sort(), which sorts the filenames in Natural sorting order. Based on my testing i found that having .png messes up sorting order. Have a look at the below code
Just thought I'd add to this (with the most concise solution I could find):
The above pads any numbers in the string to the max length of all numbers in all strings and uses the resulting string to sort.
The cast to (
int?
) is to allow for collections of strings without any numbers (.Max()
on an empty enumerable throws anInvalidOperationException
).The easiest thing to do is just P/Invoke the built-in function in Windows, and use it as the comparison function in your
IComparer
:Michael Kaplan has some examples of how this function works here, and the changes that were made for Vista to make it work more intuitively. The plus side of this function is that it will have the same behaviour as the version of Windows it runs on, however this does mean that it differs between versions of Windows so you need to consider whether this is a problem for you.
So a complete implementation would be something like:
None of the existing implementations looked great so I wrote my own. The results are almost identical to the sorting used by modern versions of Windows Explorer (Windows 7/8). The only differences I've seen are 1) although Windows used to (e.g. XP) handle numbers of any length, it's now limited to 19 digits - mine is unlimited, 2) Windows gives inconsistent results with certain sets of Unicode digits - mine works fine (although it doesn't numerically compare digits from surrogate pairs; nor does Windows), and 3) mine can't distinguish different types of non-primary sort weights if they occur in different sections (e.g. "e-1é" vs "é1e-" - the sections before and after the number have diacritic and punctuation weight differences).
The signature matches the
Comparison<string>
delegate:Here's a wrapper class for use as
IComparer<string>
:Example:
Here's a good set of filenames I use for testing:
I've actually implemented it as an extension method on the
StringComparer
so that you could do for example:StringComparer.CurrentCulture.WithNaturalSort()
orStringComparer.OrdinalIgnoreCase.WithNaturalSort()
.The resulting
IComparer<string>
can be used in all places likeOrderBy
,OrderByDescending
,ThenBy
,ThenByDescending
,SortedSet<string>
, etc. And you can still easily tweak case sensitivity, culture, etc.The implementation is fairly trivial and it should perform quite well even on large sequences.
I've also published it as a tiny NuGet package, so you can just do:
The code including XML documentation comments and suite of tests is available in the NaturalSort.Extension GitHub repository.
The entire code is this (if you cannot use C# 7 yet, just install the NuGet package):