C # Linq Custom Sort

I have a query in linqtosql that returns LabelNumber:

var q = from list in db.Lists select list.LabelNumber; 

var q then becomes an IEnumerable<string> with the following elements:

 {"1","2","2.A","2.B","3","3.A","3.B"} 

Basically I want to arrange the elements as they appear above, but I cannot use OrderBy(x=>x.LabelNumber) , because "10" will be placed after "1" and before "2" .

I suppose I need to write a custom comparator function, but how to do it with linq?

Edit: I think all of the answers below will work, but for all the answers you need to add one warning.

If you use Linq2SQL, you cannot use array indices in a query. To overcome this, you must have two requests. One that reads from SQL. Second order:

 var q = from list in db.Lists select list.LabelNumber; var q2 = q.AsEnumerable() .OrderBy(x => int.Parse(x.LabelNumber.Split('.')[0])) .ThenBy(x => x.Number .Contains(".") ? x.LabelNumber.Split('.')[1].ToString() : string.Empty); 
+6
c # linq
source share
4 answers

You probably don't need to write a custom mapper. If all your tags are in the form of number.letter , you can use this.

 var query = from list in db.Lists let split = list.LabelNumber.Split('.') let order = split.Length == 1 ? new { a = int.Parse(split[0]), b = String.Empty } : new { a = int.Parse(split[0]), b = split[1] } orderby order.a, order.b select list.LabelNumber; 

If you need more control, you can always convert the sort fields ( a and b ) to the appropriate types, rather than int and strings.


If it is LINQ-to-SQL, this will not actually work, as some of the methods used here are not supported. Here is a friendly version of LINQ-to-SQL. This will not give the most beautiful request, but it will work.

 var query = from list in db.Lists let dot = list.LabelNumber.IndexOf('.') let name = list.LabelNumber let order = dot == -1 ? new { a = Convert.ToInt32(name.Substring(0, dot)), b = String.Empty } : new { a = Convert.ToInt32(name.Substring(0, dot)), b = name.Substring(dot+1) } orderby order.a, order.b select list.LabelNumber; 
+9
source share
 OrderBy(x=>x.LabelNumber, new AlphanumComparator()) 

where AlphanumComparator is David Coellโ€™s excellent natural sorting algorithm. No need to reinvent the wheel.

If you intend to use the C # version, change it to:

 AlphanumComparator : IComparer<string> 

and

 public int Compare(string x, string y) 
+11
source share

If you are sure q well formatted and ordered:

 var result = q.OrderBy(x => int.Parse(x.Split('.')[0])); 
+1
source share

Here is my contribution. Using Regular Expression and LAMBDA expression

 List<String> Lst = new List<string> { "1", "2", "2.A","10.A", "2.C", "3", "3.A", "3.B","2.B","11.D" }; Lst = Lst.Select(X => new { Number = int.Parse( Regex.Match(X, @"([0-9]*).?([a-zA-Z]*)").Groups[1].Value), Strings=Regex.Match(X, @"([0-9]*).?([a-zA-Z]*)").Groups[2].Value, OriginalString = X }).OrderBy(X => X.Number).ThenBy(X=>X.Strings) .Select(X => X.OriginalString).ToList(); 

Exit:

 "1" "2" "2.A" "2.B" "2.C" "3" "3.A" "3.B" "10.A" "11.D" 
0
source share

All Articles