Используйте очередь из последних N элементов. Когда приходит следующий элемент, выдавайте самый старый; остаток очереди после конца потока не выдаётся.
Однопроходный фильтр последовательности с исключением последних N элементов
Используйте очередь из последних N элементов. Когда приходит следующий элемент, выдавайте самый старый; остаток очереди после конца потока не выдаётся.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Реализуйте функцию FilterLast, которая возвращает все элементы исходного потока, за исключением последних N элементов. При этом исходный поток нельзя обходить более одного раза и нельзя сохранять его полностью в памяти, так как его длина заранее неизвестна (вызов source.Count() потребует полного перечисления). Требования к решению:
- использовать одно‑проходный потоковый алгоритм;
- значение N значительно меньше длины последовательности;
- допускается дополнительная память лишь для небольшого количества элементов (буфер размером N).
IEnumerable<T> FilterLast<T>(IEnumerable<T> source, Int32 skipCount)
Ответ
Используйте очередь из последних N элементов. Когда приходит следующий элемент, выдавайте самый старый; остаток очереди после конца потока не выдаётся.
static IEnumerable<T> FilterLast<T>(IEnumerable<T> source, int skipCount)
{
ArgumentNullException.ThrowIfNull(source);
if (skipCount < 0) throw new ArgumentOutOfRangeException(nameof(skipCount));
return Iterate();
IEnumerable<T> Iterate()
{
var buffer = new Queue<T>();
foreach (var item in source)
{
if (skipCount == 0) { yield return item; continue; }
if (buffer.Count == skipCount) yield return buffer.Dequeue();
buffer.Enqueue(item);
}
}
}
Время O(n), память O(min(n, N)); повторного перечисления нет. При N = 0 выдаётся весь поток, при N не меньше длины — пустой результат. Проверки аргументов выполняются сразу, а перечисление остаётся ленивым.