The answers so far are great! But I see a need for a solution with the following constraints:
- Plain, concise LINQ;
- O(n) complexity;
- Do not evaluate the property more than once per element.
Here it is:
public static T MaxBy(this IEnumerable en, Func evaluate) where R : IComparable {
return en.Select(t => new Tuple(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) > 0 ? next : max).Item1;
}
public static T MinBy(this IEnumerable en, Func evaluate) where R : IComparable {
return en.Select(t => new Tuple(t, evaluate(t)))
.Aggregate((max, next) => next.Item2.CompareTo(max.Item2) < 0 ? next : max).Item1;
}
Usage:
IEnumerable> list = new[] {
new Tuple("other", 2),
new Tuple("max", 4),
new Tuple("min", 1),
new Tuple("other", 3),
};
Tuple min = list.MinBy(x => x.Item2); // "min", 1
Tuple max = list.MaxBy(x => x.Item2); // "max", 4