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
:
public class Data { public int Id; public string Name; public int Rank; }
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.
Leave a comment