using System; using System.Collections.Generic; namespace Superlazy { public static class SLLinqUtil { public static TSource MinBy(this IEnumerable source, Func selector) { return source.MinBy(selector, null); } public static TSource MinBy(this IEnumerable source, Func selector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (selector == null) throw new ArgumentNullException("selector"); if (comparer == null) comparer = Comparer.Default; using var sourceIterator = source.GetEnumerator(); if (!sourceIterator.MoveNext()) { throw new InvalidOperationException("Sequence contains no elements"); } var min = sourceIterator.Current; var minKey = selector(min); while (sourceIterator.MoveNext()) { var candidate = sourceIterator.Current; var candidateProjected = selector(candidate); if (comparer.Compare(candidateProjected, minKey) < 0) { min = candidate; minKey = candidateProjected; } } return min; } public static TSource MaxBy(this IEnumerable source, Func selector) { return source.MaxBy(selector, null); } public static TSource MaxBy(this IEnumerable source, Func selector, IComparer comparer) { if (source == null) throw new ArgumentNullException("source"); if (selector == null) throw new ArgumentNullException("selector"); if (comparer == null) comparer = Comparer.Default; using var sourceIterator = source.GetEnumerator(); if (!sourceIterator.MoveNext()) { throw new InvalidOperationException("Sequence contains no elements"); } var max = sourceIterator.Current; var maxKey = selector(max); while (sourceIterator.MoveNext()) { var candidate = sourceIterator.Current; var candidateProjected = selector(candidate); if (comparer.Compare(candidateProjected, maxKey) > 0) { max = candidate; maxKey = candidateProjected; } } return max; } } }