Millerbean
Millerbean

Reputation: 295

Natural numeric sort in C#

I have a problem when sorting a generic list in C#

I have a List<MyObjects> myList, and MyObject has a string property.

Now it looks like this when sorting descending

2.4.88

2.4.70

2.4.164 -> this is wrong

2.4.15

How do I sort my list?

I have tried:

myList.sort(delegate(MyObjects obj1, MyObjects obj2)
{
    return obj2.version.CompareTo(obj1.version);
});

Its not an option to use Linq (older framework)

UPDATE: My list can also contains N/A

Upvotes: 4

Views: 2390

Answers (6)

Oliver
Oliver

Reputation: 45101

Maybe one on these may help you:

Upvotes: 1

softveda
softveda

Reputation: 11066

If your string pattern fits the .Net version class then convert it to a Version object and compare.

Upvotes: 1

Paul Tyng
Paul Tyng

Reputation: 7584

You cannot compare as strings, because obviously thats the proper string sorting. You need to parse to numbers or to an instance of the Version class:

myList.sort(delegate(MyObjects obj1, MyObjects obj2)
{
    return new Version(obj2.version).CompareTo(new Version(obj1.version));
});

Upvotes: 3

Svish
Svish

Reputation: 158081

I had to do natural sorting a while ago. Don't remember where I found the code, but stuck it on my blog for future reference: http://www.geekality.net/2009/03/02/natural-sorting

Here's the code:

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

namespace NaturalSort
{
     public sealed class NaturalStringComparer : IComparer<string>
     {
         private readonly int modifier = 1;

         public NaturalStringComparer(bool descending)
         {
             if (descending)
                 modifier = -1;
         }

         public NaturalStringComparer()
             :this(false) {}

         public int Compare(string a, string b)
         {
             return SafeNativeMethods.StrCmpLogicalW(a ?? "", b ?? "") * modifier;
         }
     }

     public sealed class NaturalFileInfoComparer : IComparer<FileInfo>
     {
         public int Compare(FileInfo a, FileInfo b)
         {
             return SafeNativeMethods.StrCmpLogicalW(a.Name ?? "", b.Name ?? "");
         }
     }

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

You'd use it along these lines:

myList.Sort(new NaturalStringComparer(true));

Upvotes: 3

Sumit Gupta
Sumit Gupta

Reputation: 2192

Can you describe how it is wrong. Looks like it is perfectly placed in order. However, just a random suggestion, if you are sure of format you can break the string and convert to number to check this kind of stuff.

Upvotes: -1

Marc Gravell
Marc Gravell

Reputation: 1062965

Perhaps sort via Version?

return (Version.Parse(obj2.version)).CompareTo(Version.Parse(obj1.version));

of course, it will be cheaper if you do the parsing once and once only (maybe make version a Version instead of a string)

Upvotes: 2

Related Questions