How would I sort a list of files by name to match how Windows Explorer displays them?
Asked Answered
S

4

4

Let's say I've sorted a list of files in Explorer by name, like so:

2009-06-02-4.0.9.txt
2009-06-02-4.0.10.txt
2009-06-02-4.0.11.txt
2009-06-02-4.0.12.txt

I have a FileInfo Comparer that sorts an array of FileInfo objects by name:

    class FileInfoComparer : IComparer<FileInfo> {
        public int Compare(FileInfo x, FileInfo y) {
            return string.Compare(x.FullName, 
                                  y.FullName, 
                                  StringComparison.OrdinalIgnoreCase);
        }
    }

Sorting that same list of files from above using this Comparer yields:

2009-06-02-4.0.10.txt
2009-06-02-4.0.11.txt
2009-06-02-4.0.12.txt
2009-06-02-4.0.9.txt

which is problematic, as the order is extremely important.

I would imagine there's a way to mimic what Windows is doing in C# code, but I have yet to find a way. Any help is appreciated!

Thanks!

Springing answered 18/6, 2009 at 14:34 Comment(1)
possible duplicate of Natural Sort Order in C#Disappointment
M
12

Windows Explorer uses an API called:

StrCmpLogicalW

to perform the sort in a "logical" manner.

Someone has also implemented a class in C# which will do this for you.

Monostome answered 18/6, 2009 at 14:44 Comment(0)
G
4

You can also use P/Invoke to call the win32 API. This would be the most consistent behavior, and might perform better (I would benchmark both options). Even the code project link isn't entirely consistent with the windows behavior and it isn't future proof.

Glycogen answered 18/6, 2009 at 14:42 Comment(0)
C
2

You need a natural numeric sort which unfortunately there isn't a native implementation of in the .NET framework. This article on CodeProject will tell you all you need to know about making your own .NET clone.

Cleopatra answered 18/6, 2009 at 14:44 Comment(1)
Implementing your own version of StrCmpLogicalW in managed code is the best option and the code project article makes that quite easy.Curve
O
-1

Sometimes, depending on the data, you can just do this:

using System.Linq;         
...

    string[] dirs = _fileSystem.GetDirectories(_root);
    dirs = dirs.OrderBy(x => x.Length).ThenBy(x => x);

This works for the sample data you have in your question.

Obviate answered 23/5, 2020 at 20:50 Comment(3)
While true that it would sometimes work, I don't think this algorithm is very helpful, since it would sort badly in a lot of cases. Consider ["2009-06-02-3.0.100.txt", "2009-06-02-4.0.1.txt"]. This algorithm would sort sort 4.0.1 before 3.0.100.Sidereal
@Sidereal It looks like the process that creates the file names is consistent and wouldn't create one with a totally different pattern.Obviate
I believe my examples follow the same pattern as the examples in the question.Sidereal

© 2022 - 2024 — McMap. All rights reserved.