Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Общие вопросы по .NET и C# > Вопрос по использованию IEnumerable


Автор: Kill_em_all 10.2.2014, 15:59
Доброго времени суток. Сегодня был на собеседовании и гордо провалил техническое интервью. 
Задание, на котором я свалился: необходимо написать функцию, которая возвращает IEnumerable<int> без n последних элементов. Исходные данные - большая коллекция представленная IEnumerable<int>. Лишний раз проходить по списку нельзя, а по сему нельзя было использовать Count() и Reverse()

Возможно ли решить эту задачу с такими условиями? Я спросил интервьюера после: какое же решение? Но он невнятно что-то пробубнил про временный буффер, yield return и т.д, а допытываться я не стал и поверил на слово =)

Автор: jonie 10.2.2014, 18:34
Цитата(Kill_em_all @  10.2.2014,  16:59 Найти цитируемый пост)
без n последних элементов

быть может речь всеже шла про "без n или менее n последних элеменов" ?
т.к. с точным значеним n (без выделения памяти под весь массив (чтобы понять длину)) все будет мягко говоря сложновато...
а вот с моим условие просто:
Код

 static IEnumerable<T> LimitIEnumerable<T>(int n, IEnumerable<T> enumerable)
        {
            var buf = new T[n];
            var e = enumerable.GetEnumerator();
            while (true)
            {
                int i = 0;
                while (e.MoveNext())
                {
                    buf[i++] = e.Current;
                    if (i >= n) break;
                }
                if (i < n) yield break;

                foreach (var be in buf)
                {
                    yield return be;
                }
            }
        }

Автор: infarch 10.2.2014, 19:19
Вот такая функция пришла в голову:
Код

        static IEnumerable<int> GetIE(IEnumerable<int> input, int n)
        {
            var ie=input.GetEnumerator();
            int[] buffer = new int[n];
            int ptr = 0;
            while (ptr < n && ie.MoveNext())
            {
                buffer[ptr++] = ie.Current;
            }
            int length = ptr;
            ptr--;
            while (ie.MoveNext())
            {
                int i = buffer[0];
                int[] tmp = new int[length];
                Array.Copy(buffer, 1, tmp, 0, ptr);
                buffer = tmp;
                buffer[ptr] = ie.Current;
                yield return i;
            }
        }


Автор: diadiavova 10.2.2014, 23:56
Да собственно проходишь коллекцию в цикле, первые n элементов просто добавляешь в очередь, дальше (начиная с n+1) при добавлении элемента в конец очереди, из начала извлекаешь элемент и йилдишь его. Таким образом йилд будет отставать от извлечения из входной коллекции как раз на n элементов. Когда во входной коллекции элементы закончатся, в очереди останутся n элементов неотйилденными, где и будут благополучно похоронены. Код писать лень, да в принципе он и так понятен.

ЗЫ
Честно говоря, без подсказки про буфер не догадался бы.

Автор: Kill_em_all 11.2.2014, 08:15
Спасибо за ответы. Теперь понятно. Я уже думал, что условие или некорректно или я его не так понял. Провал на интервью абсолютно заслужен =)

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)