Страницы

Поиск по вопросам

пятница, 3 января 2020 г.

Как избежать множественного перечисления IEnumerable?

#c_sharp #linq


Есть метод, возвращающий последовательность, состоящую из пар соседних элементов.
Например, по последовательности {1,2,3} метод должен вернуть две пары: (1,2) и (2,3).

Решение, которое сразу пришло в голову:

return items 
    .Take(items.Count() - 1) 
    .Zip(items.Skip(1), Tuple.Create);


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


Ответы

Ответ 1



Например, так. Объявим метод расширения, который выдаёт последовательные пары: public static class EnumerableExtensions { public static IEnumerable Pairwise( this IEnumerable sequence, Func selector) { using (var it = sequence.GetEnumerator()) { if (!it.MoveNext()) yield break; T prev = it.Current; while (it.MoveNext()) yield return selector(prev, prev = it.Current); } } } И пользуемся: return items.Pairwise(Tuple.Create);

Ответ 2



Как насчет отдельной функции? public IEnumerable> GetItems(IEnumerable source) { var prev = default(T); var firstVisited = false; foreach(var item in source) { if (firstVisited) { yield return Tuple.Create(prev, item); } else { firstVisited = true; } prev = item; } }

Комментариев нет:

Отправить комментарий