From 3d360392532db6cd2dcccdd803eb3d9bf98a142a Mon Sep 17 00:00:00 2001 From: Stuart Turner Date: Fri, 25 Nov 2022 20:35:36 -0600 Subject: [PATCH] Simplify ZipLongest implementation --- MoreLinq/ZipLongest.cs | 65 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/MoreLinq/ZipLongest.cs b/MoreLinq/ZipLongest.cs index d0f663438..66fd3747e 100644 --- a/MoreLinq/ZipLongest.cs +++ b/MoreLinq/ZipLongest.cs @@ -19,6 +19,7 @@ namespace MoreLinq { using System; using System.Collections.Generic; + using System.Linq; static partial class MoreEnumerable { @@ -56,13 +57,13 @@ static partial class MoreEnumerable public static IEnumerable ZipLongest( this IEnumerable first, IEnumerable second, - Func resultSelector) + Func resultSelector) { if (first == null) throw new ArgumentNullException(nameof(first)); if (second == null) throw new ArgumentNullException(nameof(second)); if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - return ZipImpl(first, second, null, null, (a, b, _, _) => resultSelector(a, b), 1); + return ZipLongestImpl(first, second, Enumerable.Repeat(default(object?), int.MaxValue), Enumerable.Repeat(default(object?), int.MaxValue), (a, b, _, _) => resultSelector(a, b), 2); } /// @@ -103,14 +104,14 @@ public static IEnumerable ZipLongest( this IEnumerable first, IEnumerable second, IEnumerable third, - Func resultSelector) + Func resultSelector) { if (first == null) throw new ArgumentNullException(nameof(first)); if (second == null) throw new ArgumentNullException(nameof(second)); if (third == null) throw new ArgumentNullException(nameof(third)); if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - return ZipImpl(first, second, third, null, (a, b, c, _) => resultSelector(a, b, c), 2); + return ZipLongestImpl(first, second, third, Enumerable.Repeat(default(object?), int.MaxValue), (a, b, c, _) => resultSelector(a, b, c), 3); } /// @@ -155,7 +156,7 @@ public static IEnumerable ZipLongest( IEnumerable second, IEnumerable third, IEnumerable fourth, - Func resultSelector) + Func resultSelector) { if (first == null) throw new ArgumentNullException(nameof(first)); if (second == null) throw new ArgumentNullException(nameof(second)); @@ -163,7 +164,59 @@ public static IEnumerable ZipLongest( if (fourth == null) throw new ArgumentNullException(nameof(fourth)); if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - return ZipImpl(first, second, third, fourth, resultSelector, 3); + return ZipLongestImpl(first, second, third, fourth, resultSelector, 4); + } + + private static IEnumerable ZipLongestImpl( + IEnumerable s1, + IEnumerable s2, + IEnumerable s3, + IEnumerable s4, + Func resultSelector, + int limit) + { + using var e1 = s1.GetEnumerator(); + using var e2 = s2.GetEnumerator(); + using var e3 = s3.GetEnumerator(); + using var e4 = s4.GetEnumerator(); + + while (true) + { + var terms = 4; + + var v1 = default(T1?); + if (e1.MoveNext()) + { + v1 = e1.Current; + terms--; + } + + var v2 = default(T2?); + if (e2.MoveNext()) + { + v2 = e2.Current; + terms--; + } + + var v3 = default(T3?); + if (e3.MoveNext()) + { + v3 = e3.Current; + terms--; + } + + var v4 = default(T4?); + if (e4.MoveNext()) + { + v4 = e4.Current; + terms--; + } + + if (terms >= limit) + yield break; + + yield return resultSelector(v1, v2, v3, v4); + } } } }