Click here to Skip to main content
15,890,690 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I have a list model
public class KitModel
{
public string KitName { get; set; }
public string KitCode { get; set; }
public decimal KitValue { get; set; }
}
List<kitmodel> listKitModel=new List<kitmodel>();
having data like this
listKitModel[0].KitCode ="BIN"
listKitModel[1].KitCode ="CAN9"
listKitModel[0].KitCode ="CAN8"
listKitModel[0].KitCode ="CAN10"
listKitModel[0].KitCode ="CAN11"
listKitModel[0].KitCode ="CAN12"

What I have tried:

i sort like this
listKitModel= listKitModel.OrderBy(x => x.KitCode).ToList();

Am getting out like this
listKitModel[0].KitCode ="BIN"
listKitModel[0].KitCode ="CAN10"
listKitModel[0].KitCode ="CAN11"
listKitModel[0].KitCode ="CAN12"
listKitModel[1].KitCode ="CAN8"
listKitModel[0].KitCode ="CAN9"
But Expected output is asc
listKitModel[0].KitCode ="BIN"
listKitModel[0].KitCode ="CAN8"
listKitModel[1].KitCode ="CAN9"
listKitModel[0].KitCode ="CAN10"
listKitModel[0].KitCode ="CAN11"
listKitModel[0].KitCode ="CAN12"
Posted
Updated 27-Jul-18 21:53pm
Comments
Eric Lynch 26-Jul-18 16:15pm    
You'd need to clarify your rules for ordering better. As far as a string compare is concerned, CAN10 comes before CAN8 ("1" comes before "8").

Func<string, string> mySort = ( s ) => {
   string alphas = s.PadRight( 3 ).Substring( 0, 3 );
   string digitChars = s.PadRight( 5, ' ' ).Substring( 3, 2 ).Trim();
   int digits = string.IsNullOrEmpty( digitChars ) ? 0 : int.Parse( digitChars );

   return $"{alphas}{digits:D2}";
};

var q = listKitModel.OrderBy( x => mySort( x.KitCode ) ).ToList();
 
Share this answer
 
C#
public class KitModel
{
    public string KitName { get; set; }
    public string KitCode { get; set; }
    public decimal KitValue { get; set; }

    public string KitCodePrefix { get; set; }
    public int KitIndex { get; set; }
}


C#
List<KitModel> lst = new List<KitModel>();

lst.Add(new KitModel()
{
    KitCode = "BIN",
    KitCodePrefix = "BIN",
    KitIndex = 0
});
lst.Add(new KitModel()
{
    KitCode = "CAN8",
    KitCodePrefix = "CAN",
    KitIndex = 8
});
lst.Add(new KitModel()
{
    KitCode = "CAN9",
    KitCodePrefix = "CAN",
    KitIndex = 9
});
lst.Add(new KitModel()
{
    KitCode = "CAN12",
    KitCodePrefix = "CAN",
    KitIndex = 12
});

lst.Sort(delegate (KitModel x, KitModel y)
{
    int a = x.KitCodePrefix.CompareTo(y.KitCodePrefix);
    if (a == 0)
        a = x.KitIndex.CompareTo(y.KitIndex);
    return a;
});
 
Share this answer
 
Comments
Eric Lynch 27-Jul-18 11:16am    
Or, make the class IComparable<T>, and call list.Sort() without a parameter, for example:

public class KitModel : IComparable<KitModel>
{
public string KitName { get; set; }
public string KitCode { get; set; }
public decimal KitValue { get; set; }
public string KitCodePrefix { get; set; }
public int KitIndex { get; set; }

public int CompareTo(KitModel other)
{
if (other == null)
return 1;

int comparison = KitCodePrefix.CompareTo(other.KitCodePrefix);
return comparison != 0 ? comparison : KitIndex.CompareTo(other.KitIndex);
}
}

My suggestion would be to write a custom Comparer.The comparer could split off both the word prefix and the numeric suffix part of the KitCode. Then it could use string.Compare to compare the prefixes and use CompareTo to compare the numeric suffixes.

C#
class KitCodeComparer : IComparer<string>
   {
       public int Compare(string x, string y)
       {
           char[] digits = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' };
           int intpos = x.IndexOfAny(digits);
           string wordPrefixX = intpos == -1 ? x : x.Substring(0, intpos);
           int numericSuffixX = intpos == -1 ? intpos : int.Parse(x.Substring(intpos));
           intpos = y.IndexOfAny(digits);
           string wordPrefixY = intpos == -1 ? y : y.Substring(0, intpos);
           int numericSuffixY = intpos == -1 ? intpos : int.Parse(y.Substring(intpos));
           int result = string.Compare(wordPrefixX, wordPrefixY);
           if(result==0)
           {
               result = numericSuffixX.CompareTo(numericSuffixY);
           }
           return result;
       }

   }

The comparer can be used like this.

C#
List<string> testStrings = new List<string>()
           {
               "BIN","CAN9","CAN8","CAN10","CAN11","CAN12"
           };
           testStrings.Sort(new KitCodeComparer());
           testStrings.ForEach(s => Console.WriteLine(s));

 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900