Примечание: Начиная с .NET 4.0, фреймворк включает в себя метод расширения .Zip
для IEnumerable, документированный здесь . Следующее поддерживается для потомков и для использования в .NET Framework версии ранее 4.0.
Я использую следующие методы расширения:
// From http://community.bartdesmet.net/blogs/bart/archive/2008/11/03/c-4-0-feature-focus-part-3-intermezzo-linq-s-new-zip-operator.aspx
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> func) {
if (first == null)
throw new ArgumentNullException("first");
if (second == null)
throw new ArgumentNullException("second");
if (func == null)
throw new ArgumentNullException("func");
using (var ie1 = first.GetEnumerator())
using (var ie2 = second.GetEnumerator())
while (ie1.MoveNext() && ie2.MoveNext())
yield return func(ie1.Current, ie2.Current);
}
public static IEnumerable<KeyValuePair<T, R>> Zip<T, R>(this IEnumerable<T> first, IEnumerable<R> second) {
return first.Zip(second, (f, s) => new KeyValuePair<T, R>(f, s));
}
РЕДАКТИРОВАТЬ : после комментариев я обязан уточнить и исправить некоторые вещи:
- Первоначально я взял первый дословный вариант реализации Zip из блога Барта де Смета
- Добавлена утилита перечисления (которая была также отмечена в исходном сообщении Барта)
- Добавлена проверка нулевых параметров (также обсуждается в посте Барта)