Search code examples
c#linq

Sort List<T> Multiple properties alphabetically and numerically


I have the following list with 3 columns. Column 3 is of type string, when trying to identify if it is an integer

Col1    Col2    Col3

0000    Item0   1
0000    Item0   10
0000    Item0   11
0000    Item0   12
0000    Item0   2
0000    Item0   3

0000    Item1   P1
0000    Item1   P10
0000    Item1   P11
0000    Item1   P12
0000    Item1   P2
0000    Item1   P3

when i try to sort it as follows, the last column is not sorted by field type

var orderedCustomers = Object.OrderBy(c => c.Col1).ThenBy(c => c.Col2).ThenBy(d => d.Col3);

Has anyone been through something similar, I want column 3 to be sorted asc but first numerically?

the result I am looking for is:

Col1    Col2    Col3

0000    Item0   1
0000    Item0   2
0000    Item0   3
0000    Item0   10
0000    Item0   11
0000    Item0   12

0000    Item1   P1
0000    Item1   P2
0000    Item1   P3
0000    Item1   P10
0000    Item1   P11
0000    Item1   P12

Solution

  • This can be done with a few helper methods to split and extract data from Col3.

    • First we take the non-numeric prefix (or "" if there isn't any) and sort by that.

    • Then we take the numeric suffix, convert it to an int value and sort by that as well. (I'm using int.MaxValue if there is no numeric suffix, you could use 0 or -1 if that suits you better)

    var orderedCustomers = Object
       .OrderBy(c => c.Col1)
       .ThenBy(c => c.Col2)
       .ThenBy(d => TxtPart(d.Col3))
       .ThenBy(d => NumPart(d.Col3));
    
    // Helper methods
    
    public static string TxtPart(string s) => Regex.Match(s, @"^[^0-9]*").Value;
    
    public static int NumPart(string s) => int.TryParse(Regex.Match(s, @"[0-9]*$").Value, out int v) ? v : int.MaxValue;
    

    See this Fiddle: https://dotnetfiddle.net/bfVTSr

    Output:

    0000, Item0, 1
    0000, Item0, 2
    0000, Item0, 3
    0000, Item0, 10
    0000, Item0, 11
    0000, Item0, 12
    0000, Item1, P1
    0000, Item1, P2
    0000, Item1, P3
    0000, Item1, P10
    0000, Item1, P11
    0000, Item1, P12