Linq OrderBy against specific values

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