using System.Collections.Generic; namespace System.Linq { public static class LinqExtension { public static IEnumerable ZipLongest(this IEnumerable left, IEnumerable right) { IEnumerator leftEnumerator = left.GetEnumerator(); IEnumerator rightEnumerator = right.GetEnumerator(); bool hasLeft = leftEnumerator.MoveNext(); bool hasRight = rightEnumerator.MoveNext(); while (hasLeft || hasRight) { if (hasLeft && hasRight) { yield return new T[] { leftEnumerator.Current, rightEnumerator.Current }; } else if (hasLeft) { yield return new T[] { leftEnumerator.Current, default(T) }; } else if (hasRight) { yield return new T[] { default(T), rightEnumerator.Current }; } hasLeft = leftEnumerator.MoveNext(); hasRight = rightEnumerator.MoveNext(); } } public static IEnumerable DistinctBy (this IEnumerable source, Func keySelector) { if (source != null) { var seenKeys = new HashSet(); foreach (TSource element in source) { if (seenKeys.Add(keySelector(element))) { yield return element; } } } } public static IList Materialize(this IEnumerable source) { if (source is IList) { // Already a list, use it as is return (IList)source; } else { // Not a list, materialize it to a list return source.ToList(); } } public static IEnumerable> Chunkify(this IEnumerable source, int size) { if (source == null) { yield break; } if (size <= 0) { throw new ArgumentException("chunkSize must be greater than 0."); } while (source.Any()) { yield return source.Take(size); source = source.Skip(size); } } } }