0

I have a List which is being returned from a WCF service ,for List of files on Server. Which i am later using to populate the TreeView in my Client Application

I need the list to be in naturally sorted order.

For ex : I have a list something like List-1 , and my expected result is List-2 but i get List-3 as my output.(refer list given below)

List-1          List-2          List-3
abc.jpg         abc.jpg         abc.jpg
abc10.jpg       abc10.jpg       abc10.jpg
abc100.jpg      abc97.jpg       abc100.jpg
abc98.jpg       abc98.jpg       abc101.jpg
abc97.jpg       abc100.jpg      abc102.jpg
abc102.jpg      abc101.jpg      abc97.jpg
abc101.jpg      abc102.jpg      abc98.jpg

So far i have looked into the stackoverflow's post :

[1] :C# Sort files by natural number ordering in the name? [2]: Sorting a FileInfo[] based using Natural Sorting on the filename (SQL files) .

None of them found to working for my case , Any help would be appreciated :)

Community
  • 1
  • 1
coder3521
  • 2,608
  • 1
  • 28
  • 50
  • Are your file names always contains non-numeric chars and then optional numbers? – Zohar Peled Jul 21 '15 at 11:55
  • How about [Natural Sort Order in C#](http://stackoverflow.com/questions/248603/natural-sort-order-in-c-sharp) or [Natural Sorting in C#](http://www.interact-sw.co.uk/iangblog/2007/12/13/natural-sorting)? – crashmstr Jul 21 '15 at 11:58
  • No it could be anything .. How we give file names in any file system – coder3521 Jul 21 '15 at 12:18

1 Answers1

3

Here you go; a handy list extension for natural sorting:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Demo
{
    // A List extension class for natural sorting.

    public static class ListExt
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        private static extern int StrCmpLogicalW(string lhs, string rhs);

        // Version for lists of any type.
        public static void SortNatural<T>(this List<T> self, Func<T, string> stringSelector)
        {
            self.Sort((lhs, rhs) => StrCmpLogicalW(stringSelector(lhs), stringSelector(rhs)));
        }

        // Simpler version for List<string>
        public static void SortNatural(this List<string> self)
        {
            self.Sort(StrCmpLogicalW);
        }
    }

    // Demonstrate using the List extension.

    public class Program
    {
        private static void Main(string[] args)
        {
            var names = new List<FileInfo>
            {
                new FileInfo("abc.jpg"),
                new FileInfo("abc10.jpg"),
                new FileInfo("abc100.jpg"),
                new FileInfo("abc98.jpg"),
                new FileInfo("abc97.jpg"),
                new FileInfo("abc102.jpg"),
                new FileInfo("abc101.jpg")
            };

            names.SortNatural(x => x.Name);

            foreach (var name in names)
                Console.WriteLine(name);
        }
    }
}

The output from this program is:

abc.jpg
abc10.jpg
abc97.jpg
abc98.jpg
abc100.jpg
abc101.jpg
abc102.jpg

This takes advantage of the Windows API StrCmpLogicalW() method which does a natural sort order comparison, and uses P/Invoke to call it.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Sorry Watson but i don't want to do this , as it's already big application , adding Dll for a simple task won't be good enough, Their should be some easier ways too. – coder3521 Jul 21 '15 at 12:15
  • 2
    @MakIndia You are not adding a DLL; that DLL is already part of the Windows API and will already be installed on all versions of Windows. I seriously doubt you will find any easier way than this (which is effectively only using one line of code to declare the P/Invoke and one line to call it...) – Matthew Watson Jul 21 '15 at 12:16
  • Just clarifying my doubts : Will it be always there i mean in all version of windows 7,8 , And what about its access permissions, What if a system is having limited access , still will it work fine . – coder3521 Jul 21 '15 at 12:21
  • 1
    @MakIndia Yes, it will work fine. It's a fundamental part of the Windows API which has been there since Windows 98. It is very VERY unlikely to be removed from any future version of Windows; that would break a LOT of applications! – Matthew Watson Jul 21 '15 at 12:39
  • Thanks a Lot @Matthew Watson It worked as expected . +1 for providing such a nice example. – coder3521 Jul 22 '15 at 10:44
  • Hi Matthew , Can you please tell me How to use this same NaturalSort For sorting a dictionary based on its key . I am not able to call it properly – coder3521 Aug 17 '15 at 06:10
  • 1
    @csharpcoder You would have to use `SortedDictionary` for this, along with a custom `IComparer` implemented using `StrCmpLogicalW()`. This is not completely trivial, and it's a different question so you should ask a new question for that. – Matthew Watson Aug 17 '15 at 08:41
  • Thanks for reply Matthew , I got the solution, I am proceeding with that , Surely i will to frame it in a question and post here to. – coder3521 Aug 17 '15 at 10:00