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
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.
This method performs a stable sort; that is, if the keys of two elements are equal, the order of the elements is preserved.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With