3

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!

Mark Carpenter
  • 17,445
  • 22
  • 96
  • 149
  • possible duplicate of [Natural Sort Order in C#](http://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp) – Peter O. May 18 '13 at 10:35

4 Answers4

11

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.

Jon Grant
  • 11,369
  • 2
  • 37
  • 58
3

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.

marr75
  • 5,666
  • 1
  • 27
  • 41
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.

Martin Harris
  • 28,277
  • 7
  • 90
  • 101
  • 1
    Implementing your own version of StrCmpLogicalW in managed code is the best option and the code project article makes that quite easy. – kingdango Mar 07 '12 at 21:08
0

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.

JBrooks
  • 9,901
  • 2
  • 28
  • 32