using System.Collections.Generic;
var source = Enumerable.Range(1, 1_000_000);
var mem0 = GC.GetTotalAllocatedBytes(true);
source.GroupBy(x => x % 1000).Select(g => g.MaxBy(x => x % 3333)).Count();
var mem1 = GC.GetTotalAllocatedBytes(true);
Console.WriteLine($"Allocated: {mem1 - mem0:#,0} bytes");
var mem0 = GC.GetTotalAllocatedBytes(true);
source.GroupMaxBy(x => x % 1000, x => x % 3333).Count();
var mem1 = GC.GetTotalAllocatedBytes(true);
Console.WriteLine($"Allocated: {mem1 - mem0:#,0} bytes");
public static IEnumerable<TSource> GroupMaxBy<TSource, TKey, TValue>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TValue> valueSelector,
IEqualityComparer<TKey> keyComparer = default,
IComparer<TValue> valueComparer = default)
valueComparer ??= Comparer<TValue>.Default;
var dictionary = new Dictionary<TKey, (TSource Item, TValue Value)>(keyComparer);
foreach (var item in source)
var key = keySelector(item);
var value = valueSelector(item);
if (dictionary.TryGetValue(key, out var existing) &&
valueComparer.Compare(existing.Value, value) >= 0) continue;
dictionary[key] = (item, value);
foreach (var entry in dictionary.Values)