Using lambda expression with .OrderBy
It's always bugged me that I could use a lambda expression with List<T>.Sort()
, but not with IEnumerable<T>.OrderBy
, i.e. given data object Data
:
you can sort List<Data>
in place like this:
data.Sort((left, right) => {
var cmp = left.Name.CompareTo(right.Name);
if(cmp != 0) {
return cmp;
}
return right.Rank.CompareTo(left.Rank);
});
But if I had an IEnumerable<Data>
, orderby needs a custom IComparer
and can't take a lambda.
Fortunately, it is fairly easy to create a generic IComparer
that does take a lambda and an extension method to simplify the signature to just a lambda expression:
public static class OrderByExtension {
private class CustomComparer<T> : IComparer<T> {
private readonly Func<T,T,int> _comparison;
public CustomComparer(Func<T,T,int> comparison) {
_comparison = comparison;
}
public int Compare(T x, T y) {
return _comparison(x, y);
}
}
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> enumerable, Func<T,T,int> comparison) {
return enumerable.OrderBy(x => x, new CustomComparer<T>(comparison));
}
public static IEnumerable<T> OrderByDescending<T>(this IEnumerable<T> enumerable, Func<T,T,int> comparison) {
return enumerable.OrderByDescending(x => x, new CustomComparer<T>(comparison));
}
}
Now I can use a lambda just like in sort:
var ordered = unordered.OrderBy((left, right) => {
var cmp = left.Name.CompareTo(right.Name);
if(cmp != 0) {
return cmp;
}
return right.Rank.CompareTo(left.Rank);
});
Of course, .OrderByDescending
is kind of redundant, since you can invert the order in the lambda just as easily, but is added simply for completeness.