Sort list of objects using natural sort

1.3k views Asked by At

I have a class

class grpa
{
    public string file_name { get; set; }
    public string folder_name { get; set; }
}

I also have 2 lists of strings.

List<string> actualfiles = new List<string>();
List<string> directoryfiles= new List<string>();

I'm using an enumerator to create a list of objects of type grpa

IEnumerator enume1 = actualfiles.GetEnumerator();
IEnumerator enume2 = directoryfiles.GetEnumerator();

List<grpa> grp_list = new List<grpa>();
while ((enume1.MoveNext()) && (enume2.MoveNext()))
{
    grp_list.Add(new grpa
    {
      file_name = enume1.Current.ToString(),
      folder_name = enume2.Current.ToString() 
    });
}

I would like to sort the list after file_name using natural sort:
I have this:

public static class SafeNativeMethods
{
    [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
    public static extern int StrCmpLogicalW(string psz1, string psz2);
}

public sealed class NaturalStringComparer : IComparer<string>
{
    #region IComparer<string> Members

    public int Compare(string x, string y)
    {
        return SafeNativeMethods.StrCmpLogicalW(x, y);
    }

    #endregion
}

If it would have been a normal string list I could have sort it using: actualfiles.Sort(new NaturalStringComparer());
But how can I sort grp_listafter file_name?

5

There are 5 answers

0
Sunil Singhal On

You can wrap NaturalString comparer with:

public sealed class GrpaComparer : IComparer<grpa>
{
    private IComparer<String> nsComparer;

    public GrpaComparer(IComparer<String> nsComparer) 
    {
      // Validate input for non-nullness
      this.nsComparer = nsComparer;
     }

    public int Compare(grpa x, grpa y)
    {
        return this.nsComparer.compare (x.file_name, y.file_name);
    }
}
0
L.B On

Just use linq

var sorted = grp_list.OrderBy(x=>x.file_name, new NaturalStringComparer ()).ToList();
0
MarcinJuraszek On

You can write another IComparer, this time IComparer<grpa>:

public sealed class GrpaComparer : IComparer<grpa>
{
    public int Compare(grpa x, grpa y)
    {
        return SafeNativeMethods.StrCmpLogicalW(x.file_name, y.file_name);
    }
}

With that you sort your list:

grp_list.Sort(new GrpaComparer());
0
Scott Chamberlain On

Similar to L.B's answer, however instead of using LINQ to sort the resulting list, use LINQ to do all the work at once, the operation you are doing with the two enumerables is a Zip

List<grpa> grp_list = actualfiles.Zip(directoryfiles, 
         (fileName, folderName) => new grpa { file_name = fileName, folder_name = folderName })
      .OrderBy(x=>x.file_name, new NaturalStringComparer())
      .ToList();
0
girishkatta9 On

Try removing the file extension name before sorting and use List.Sort(). It might work give it a shot.