/// <summary> /// <para> /// Replacement for list.OrderBy(?).Take(n) /// </para> /// <para> /// 1- Low Memory usage (since this method requires only ~"2*n" elements be in memory) /// </para> /// 2- Speed up by an order of magnitude especially when the input is large. /// </summary> public static IEnumerable <T> TakeOrdered <T, TKey>(this IEnumerable <T> list, int n, Func <T, TKey> keySelector, bool ascending = true) where TKey : IComparable <TKey> { var pq = new MyPriorityQueue <T>(n, ascending ? (Func <T, T, bool>)((a, b) => keySelector(a).CompareTo(keySelector(b)) >= 0) : (Func <T, T, bool>)((a, b) => keySelector(a).CompareTo(keySelector(b)) < 0) ); Stack <T> stack = new Stack <T>(); int count = 0; foreach (T item in list) { pq.InsertWithOverflow(item); count++; } int min = Math.Min(count, n); for (int i = 0; i < min; i++) { stack.Push(pq.Pop()); } for (int i = 0; i < min; i++) { yield return(stack.Pop()); } }