0

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
Mark Seemann
  • 225,310
  • 48
  • 427
  • 736
Pollo
  • 11
  • 2
  • Does this answer your question? [Sorting List in C#](https://stackoverflow.com/questions/3716831/sorting-liststring-in-c-sharp) – gunr2171 Aug 14 '23 at 23:45
  • The usual trick: `.ThenBy(d => d.Col3.Length).ThenBy(d => d.Col3)`, will work if within Col1 and Col2 the prefixes are equal-lenght. – Gert Arnold Aug 15 '23 at 09:12

1 Answers1

0

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
Peter B
  • 22,460
  • 5
  • 32
  • 69
  • The helper method NumPart, how would the function be if it were in .net5? – Pollo Aug 15 '23 at 02:03
  • My code works (tested) from .NET Core 3 (which comes with C# 8) and up, so that includes .NET 5 (C# 9). If you mean the ancient and almost obsolete .NET Framework (C# 6 or below), then you'll need to put the declaration of `v` outside of the `int.TryParse` call, as follows, using a regular function body: `public static int NumPart(string s) { int v; return int.TryParse(Regex.Match(s, @"[0-9]*$").Value, out v) ? v : int.MaxValue; }` – Peter B Aug 15 '23 at 14:12