Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq OrderBy against specific values

Is there a way in Linq to do an OrderBy against a set of values (strings in this case) without knowing the order of the values?

Consider this data:

A B A C B C D E 

And these variables:

string firstPref, secondPref, thirdPref;

When the values are set like so:

firstPref = 'A'; secondPref = 'B'; thirdPref = 'C'; 

Is it possible to order the data like so:

A A B B C C D E 
like image 418
Jonathan Parker Avatar asked Apr 08 '09 02:04

Jonathan Parker


People also ask

How do you do OrderBy in LINQ?

LINQ includes five sorting operators: OrderBy, OrderByDescending, ThenBy, ThenByDescending and Reverse. LINQ query syntax does not support OrderByDescending, ThenBy, ThenByDescending and Reverse. It only supports 'Order By' clause with 'ascending' and 'descending' sorting direction.

Is LINQ OrderBy stable?

This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved.

How do I get data in descending order in LINQ?

If you want to rearrange or sort the elements of the given sequence or collection in descending order in query syntax, then use descending keyword as shown in below example. And in method syntax, use OrderByDescending () method to sort the elements of the given sequence or collection.

How does OrderBy work in C#?

In a query expression, the orderby clause causes the returned sequence or subsequence (group) to be sorted in either ascending or descending order. Multiple keys can be specified in order to perform one or more secondary sort operations. The sorting is performed by the default comparer for the type of the element.


2 Answers

If you put your preferences into a list, it might become easier.

List<String> data = new List<String> { "A","B","A","C","B","C","D","E" }; List<String> preferences = new List<String> { "A","B","C" };  IEnumerable<String> orderedData = data.OrderBy(    item => preferences.IndexOf(item)); 

This will put all items not appearing in preferences in front because IndexOf() returns -1. An ad hoc work around might be reversing preferences and order the result descending. This becomes quite ugly, but works.

IEnumerable<String> orderedData = data.OrderByDescending(    item => Enumerable.Reverse(preferences).ToList().IndexOf(item)); 

The solution becomes a bit nicer if you concat preferences and data.

IEnumerable<String> orderedData = data.OrderBy(    item => preferences.Concat(data).ToList().IndexOf(item)); 

I don't like Concat() and ToList() in there. But for the moment I have no really good way around that. I am looking for a nice trick to turn the -1 of the first example into a big number.

like image 187
Daniel Brückner Avatar answered Oct 14 '22 05:10

Daniel Brückner


In addition to @Daniel Brückner answer and problem defined at the end of it:

I don't like Concat() and ToList() in there. But for the moment I have no really >good way around that. I am looking for a nice trick to turn the -1 of the first >example into a big number.

I think that the solution is to use a statement lambda instead of an expression lambda.

var data = new List<string> { "corge", "baz", "foo", "bar", "qux", "quux" }; var fixedOrder = new List<string> { "foo", "bar", "baz" }; data.OrderBy(d => {                     var index = fixedOrder.IndexOf(d);                     return index == -1 ? int.MaxValue : index;                    }); 

The ordered data is:

foo  bar  baz  corge  qux  quux  
like image 44
alexqc Avatar answered Oct 14 '22 04:10

alexqc