diff --git a/MoreLinq/EquiZip.cs b/MoreLinq/EquiZip.cs deleted file mode 100644 index edede6ef1..000000000 --- a/MoreLinq/EquiZip.cs +++ /dev/null @@ -1,213 +0,0 @@ -#region License and Terms -// MoreLINQ - Extensions to LINQ to Objects -// Copyright (c) 2008 Jonathan Skeet. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -namespace MoreLinq -{ - using System; - using System.Collections.Generic; - using System.Diagnostics; - using System.Linq; - - static partial class MoreEnumerable - { - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. An exception is thrown - /// if the input sequences are of different lengths. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// - /// Function to apply to each pair of elements. - /// - /// A sequence that contains elements of the two input sequences, - /// combined by . - /// - /// - /// The input sequences are of different lengths. - /// - /// - /// n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield "1A", - /// "2B", "3C", "4D" in turn. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable EquiZip( - this IEnumerable first, - IEnumerable second, - 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 EquiZipImpl(first, second, null, null, (a, b, c, d) => resultSelector(a, b)); - } - - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. An exception is thrown - /// if the input sequences are of different lengths. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// - /// Function to apply to each triplet of elements. - /// - /// A sequence that contains elements of the three input sequences, - /// combined by . - /// - /// - /// The input sequences are of different lengths. - /// - /// - /// n + l + c); - /// ]]> - /// The zipped variable, when iterated over, will yield "1Aa", - /// "2Bb", "3Cc", "4Dd" in turn. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable EquiZip( - this IEnumerable first, - IEnumerable second, IEnumerable third, - 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 EquiZipImpl(first, second, third, null, (a, b, c, _) => resultSelector(a, b, c)); - } - - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. An exception is thrown - /// if the input sequences are of different lengths. - /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in third sequence - /// Type of elements in fourth sequence - /// Type of elements in result sequence - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// The fourth sequence. - /// - /// Function to apply to each quadruplet of elements. - /// - /// A sequence that contains elements of the four input sequences, - /// combined by . - /// - /// - /// The input sequences are of different lengths. - /// - /// - /// n + l + c + f); - /// ]]> - /// The zipped variable, when iterated over, will yield "1AaTrue", - /// "2BbFalse", "3CcTrue", "4DdFalse" in turn. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable EquiZip( - this IEnumerable first, - IEnumerable second, IEnumerable third, IEnumerable fourth, - 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); - if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - - return EquiZipImpl(first, second, third, fourth, resultSelector); - } - - static IEnumerable EquiZipImpl( - IEnumerable s1, - IEnumerable s2, - IEnumerable s3, - IEnumerable s4, - Func resultSelector) - { - Debug.Assert(s1 != null); - Debug.Assert(s2 != null); - - const int zero = 0, one = 1; - - var limit = 1 + (s3 != null ? one : zero) - + (s4 != null ? one : zero); - - return ZipImpl(s1, s2, s3, s4, resultSelector, limit, enumerators => - { - var i = enumerators.Index().First(x => x.Value == null).Key; - return new InvalidOperationException(OrdinalNumbers[i] + " sequence too short."); - }); - } - - static readonly string[] OrdinalNumbers = - { - "First", - "Second", - "Third", - "Fourth", - // "Fifth", - // "Sixth", - // "Seventh", - // "Eighth", - // "Ninth", - // "Tenth", - // "Eleventh", - // "Twelfth", - // "Thirteenth", - // "Fourteenth", - // "Fifteenth", - // "Sixteenth", - }; - } -} diff --git a/MoreLinq/EquiZip.g.cs b/MoreLinq/EquiZip.g.cs new file mode 100644 index 000000000..97f37b883 --- /dev/null +++ b/MoreLinq/EquiZip.g.cs @@ -0,0 +1,824 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + 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 _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext()) + yield return resultSelector(e1.Current, e2.Current); + else + break; + } + else + { + if (e2.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2)> EquiZip( + this IEnumerable first, + IEnumerable second) + { + return EquiZip( + first, + second, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + 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 _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext() && e3.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current); + else + break; + } + else + { + if (e2.MoveNext() || e3.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third) + { + return EquiZip( + first, + second, + third, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext() && e3.MoveNext() && e4.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current); + else + break; + } + else + { + if (e2.MoveNext() || e3.MoveNext() || e4.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth) + { + return EquiZip( + first, + second, + third, + fourth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current); + else + break; + } + else + { + if (e2.MoveNext() || e3.MoveNext() || e4.MoveNext() || e5.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth) + { + return EquiZip( + first, + second, + third, + fourth, + fifth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + using var e6 = sixth.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext() && e6.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current, e6.Current); + else + break; + } + else + { + if (e2.MoveNext() || e3.MoveNext() || e4.MoveNext() || e5.MoveNext() || e6.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth) + { + return EquiZip( + first, + second, + third, + fourth, + fifth, + sixth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (seventh == null) throw new ArgumentNullException(nameof(seventh)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + using var e6 = sixth.GetEnumerator(); + using var e7 = seventh.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext() && e6.MoveNext() && e7.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current, e6.Current, e7.Current); + else + break; + } + else + { + if (e2.MoveNext() || e3.MoveNext() || e4.MoveNext() || e5.MoveNext() || e6.MoveNext() || e7.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh) + { + return EquiZip( + first, + second, + third, + fourth, + fifth, + sixth, + seventh, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (seventh == null) throw new ArgumentNullException(nameof(seventh)); + if (eighth == null) throw new ArgumentNullException(nameof(eighth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + using var e6 = sixth.GetEnumerator(); + using var e7 = seventh.GetEnumerator(); + using var e8 = eighth.GetEnumerator(); + + for (;;) + { + if (e1.MoveNext()) + { + if (e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext() && e6.MoveNext() && e7.MoveNext() && e8.MoveNext()) + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current, e6.Current, e7.Current, e8.Current); + else + break; + } + else + { + if (e2.MoveNext() || e3.MoveNext() || e4.MoveNext() || e5.MoveNext() || e6.MoveNext() || e7.MoveNext() || e8.MoveNext()) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7, T8)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth) + { + return EquiZip( + first, + second, + third, + fourth, + fifth, + sixth, + seventh, + eighth, + ValueTuple.Create); + } + + } +} diff --git a/MoreLinq/EquiZip.g.tt b/MoreLinq/EquiZip.g.tt new file mode 100644 index 000000000..0a5644995 --- /dev/null +++ b/MoreLinq/EquiZip.g.tt @@ -0,0 +1,163 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="System.Collections" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Linq" #> +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +<# + var ordinals = new[] + { + "", + "first", "second", "third", "fourth", + "fifth", "sixth", "seventh", "eighth" + }; + + var overloads = + Enumerable.Range(2, 7) + .Select(argCount => + Enumerable.Range(1, argCount).Select(argPosition => + new + { + IsFirst = argPosition == 1, + IsLast = argPosition == argCount, + Name = ordinals[argPosition], + Ordinal = ordinals[argPosition], + Type = $"T{argPosition}", + // Objects associated with the argument + Enumerator = $"e{argPosition}", + Value = $"v{argPosition}" + })) + .Select(args => args.ToList()) + .Select(args => + new + { + Arguments = args, + TParams = string.Join(", ", args.Select(arg => arg.Type)) + }); +#> +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { +<# foreach (var o in overloads) + { +#> + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// +<# foreach (var arg in o.Arguments) { #> + /// Type of elements in <#=arg.Name#> input sequence. +<# } #> + /// Type of elements in result sequence. +<# foreach (var arg in o.Arguments) { #> + /// The <#=arg.Ordinal#> source sequence. +<# } #> + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip<<#=o.TParams#>, TResult>( +<# foreach (var arg in o.Arguments) { #> + <#= arg.IsFirst ? "this " : "" #>IEnumerable<<#=arg.Type#>> <#=arg.Name#>, +<# } #> + Func<<#=o.TParams#>, TResult> resultSelector) + { +<# foreach (var arg in o.Arguments) { #> + if (<#=arg.Name#> == null) throw new ArgumentNullException(nameof(<#=arg.Name#>)); +<# } #> + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { +<# foreach (var arg in o.Arguments) { #> + using var <#=arg.Enumerator#> = <#=arg.Name#>.GetEnumerator(); +<# } #> + + for (;;) + { + if (<#=o.Arguments.First().Enumerator#>.MoveNext()) + { + if (<# foreach (var arg in o.Arguments.Skip(1)) { #><#=arg.Enumerator#>.MoveNext()<#= arg.IsLast ? "" : " && " #><#}#>) + yield return resultSelector(<# foreach (var arg in o.Arguments) { #><#=arg.Enumerator#>.Current<#= arg.IsLast ? "" : ", " #><#}#>); + else + break; + } + else + { + if (<# foreach (var arg in o.Arguments.Skip(1)) { #><#=arg.Enumerator#>.MoveNext()<#= arg.IsLast ? "" : " || " #><#}#>) + break; + else + yield break; + } + } + + throw new InvalidOperationException($"Sequences differ in length."); + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// +<# foreach (var arg in o.Arguments) { #> + /// Type of elements in <#=arg.Name#> input sequence. +<# } #> +<# foreach (var arg in o.Arguments) { #> + /// The <#=arg.Ordinal#> source sequence. +<# } #> + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(<#=o.TParams#>)> EquiZip<<#=o.TParams#>>( +<# foreach (var arg in o.Arguments) { #> + <#= arg.IsFirst ? "this " : "" #>IEnumerable<<#=arg.Type#>> <#=arg.Name#><#= arg.IsLast ? ")" : "," #> +<# } #> + { + return EquiZip( +<# foreach (var arg in o.Arguments) { #> + <#=arg.Name#>, +<# } #> + ValueTuple.Create); + } + +<# } #> + } +} diff --git a/MoreLinq/Extensions.g.cs b/MoreLinq/Extensions.g.cs index 9c0485718..a1499c011 100644 --- a/MoreLinq/Extensions.g.cs +++ b/MoreLinq/Extensions.g.cs @@ -650,7 +650,21 @@ public static partial class BatchExtension /// Size of buckets. /// A sequence of equally sized buckets containing elements of the source collection. /// - /// This operator uses deferred execution and streams its results (buckets and bucket content). + /// + /// This operator uses deferred execution and streams its results + /// (buckets are streamed but their content buffered). + /// + /// When more than one bucket is streamed, all buckets except the last + /// is guaranteed to have elements. The last + /// bucket may be smaller depending on the remaining elements in the + /// sequence. + /// + /// Each bucket is pre-allocated to elements. + /// If is set to a very large value, e.g. + /// to effectively disable batching by just + /// hoping for a single bucket, then it can lead to memory exhaustion + /// (). + /// /// public static IEnumerable> Batch(this IEnumerable source, int size) @@ -665,9 +679,21 @@ public static IEnumerable> Batch(this IEnumerable< /// Size of buckets. /// The projection to apply to each bucket. /// A sequence of projections on equally sized buckets containing elements of the source collection. - /// - /// This operator uses deferred execution and streams its results (buckets and bucket content). - /// + /// + /// This operator uses deferred execution and streams its results + /// (buckets are streamed but their content buffered). + /// + /// + /// When more than one bucket is streamed, all buckets except the last + /// is guaranteed to have elements. The last + /// bucket may be smaller depending on the remaining elements in the + /// sequence. + /// Each bucket is pre-allocated to elements. + /// If is set to a very large value, e.g. + /// to effectively disable batching by just + /// hoping for a single bucket, then it can lead to memory exhaustion + /// (). + /// public static IEnumerable Batch(this IEnumerable source, int size, Func, TResult> resultSelector) @@ -1298,240 +1324,607 @@ public static bool EndsWith(this IEnumerable first, IEnumerable second, [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] public static partial class EquiZipExtension { + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2)> EquiZip( + this IEnumerable first, + IEnumerable second) + => MoreEnumerable.EquiZip(first, second); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third) + => MoreEnumerable.EquiZip(first, second, third); /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. An exception is thrown + /// element from each of the input sequences. An exception is thrown /// if the input sequences are of different lengths. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. + /// The first source sequence. + /// The second source sequence. /// - /// Function to apply to each pair of elements. + /// Function to apply to each tuple of elements. /// - /// A sequence that contains elements of the two input sequences, - /// combined by . - /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. /// /// The input sequences are of different lengths. /// - /// - /// n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield "1A", - /// "2B", "3C", "4D" in turn. - /// /// /// This operator uses deferred execution and streams its results. /// - public static IEnumerable EquiZip( - this IEnumerable first, - IEnumerable second, - Func resultSelector) + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + Func resultSelector) => MoreEnumerable.EquiZip(first, second, resultSelector); + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth) + => MoreEnumerable.EquiZip(first, second, third, fourth); + /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. An exception is thrown + /// element from each of the input sequences. An exception is thrown /// if the input sequences are of different lengths. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// The third sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. /// - /// Function to apply to each triplet of elements. + /// Function to apply to each tuple of elements. /// - /// A sequence that contains elements of the three input sequences, - /// combined by . - /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. /// /// The input sequences are of different lengths. /// - /// - /// n + l + c); - /// ]]> - /// The zipped variable, when iterated over, will yield "1Aa", - /// "2Bb", "3Cc", "4Dd" in turn. - /// /// /// This operator uses deferred execution and streams its results. /// public static IEnumerable EquiZip( this IEnumerable first, - IEnumerable second, IEnumerable third, + IEnumerable second, + IEnumerable third, Func resultSelector) => MoreEnumerable.EquiZip(first, second, third, resultSelector); + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth); + /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. An exception is thrown + /// element from each of the input sequences. An exception is thrown /// if the input sequences are of different lengths. /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in third sequence - /// Type of elements in fourth sequence - /// Type of elements in result sequence - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// The fourth sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. /// - /// Function to apply to each quadruplet of elements. + /// Function to apply to each tuple of elements. /// - /// A sequence that contains elements of the four input sequences, - /// combined by . - /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. /// /// The input sequences are of different lengths. /// - /// - /// n + l + c + f); - /// ]]> - /// The zipped variable, when iterated over, will yield "1AaTrue", - /// "2BbFalse", "3CcTrue", "4DdFalse" in turn. - /// /// /// This operator uses deferred execution and streams its results. /// public static IEnumerable EquiZip( this IEnumerable first, - IEnumerable second, IEnumerable third, IEnumerable fourth, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, Func resultSelector) => MoreEnumerable.EquiZip(first, second, third, fourth, resultSelector); - } - - /// Evaluate extension. - - [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] - public static partial class EvaluateExtension - { /// - /// Returns a sequence containing the values resulting from invoking (in order) each function in the source sequence of functions. + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// /// - /// This operator uses deferred execution and streams the results. - /// If the resulting sequence is enumerated multiple times, the functions will be - /// evaluated multiple times too. + /// This operator uses deferred execution and streams its results. /// - /// The type of the object returned by the functions. - /// The functions to evaluate. - /// A sequence with results from invoking . - /// When is null. - - public static IEnumerable Evaluate(this IEnumerable> functions) => MoreEnumerable.Evaluate(functions); - } - - /// Exactly extension. - - [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] - public static partial class ExactlyExtension - { + public static IEnumerable<(T1, T2, T3, T4, T5, T6)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, sixth); /// - /// Determines whether or not the number of elements in the sequence is equals to the given integer. + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. /// - /// Element type of sequence - /// The source sequence - /// The exactly number of items a sequence must have for this - /// function to return true - /// is null - /// is negative - /// true if the number of elements in the sequence is equals - /// to the given integer or false otherwise. - /// - /// - /// The result variable will contain true. - /// - - public static bool Exactly(this IEnumerable source, int count) - => MoreEnumerable.Exactly(source, count); - - } + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// - /// ExceptBy extension. + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + Func resultSelector) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, resultSelector); - [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] - public static partial class ExceptByExtension - { /// - /// Returns the set of elements in the first sequence which aren't - /// in the second sequence, according to a given key selector. + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// /// - /// This is a set operation; if multiple elements in have - /// equal keys, only the first such element is returned. - /// This operator uses deferred execution and streams the results, although - /// a set of keys from is immediately selected and retained. + /// This operator uses deferred execution and streams its results. /// - /// The type of the elements in the input sequences. - /// The type of the key returned by . - /// The sequence of potentially included elements. - /// The sequence of elements whose keys may prevent elements in - /// from being returned. - /// The mapping from source element to key. - /// A sequence of elements from whose key was not also a key for - /// any element in . - public static IEnumerable ExceptBy(this IEnumerable first, - IEnumerable second, - Func keySelector) - => MoreEnumerable.ExceptBy(first, second, keySelector); + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, sixth, seventh); /// - /// Returns the set of elements in the first sequence which aren't - /// in the second sequence, according to a given key selector. + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// /// - /// This is a set operation; if multiple elements in have - /// equal keys, only the first such element is returned. - /// This operator uses deferred execution and streams the results, although - /// a set of keys from is immediately selected and retained. + /// This operator uses deferred execution and streams its results. /// - /// The type of the elements in the input sequences. - /// The type of the key returned by . - /// The sequence of potentially included elements. - /// The sequence of elements whose keys may prevent elements in - /// from being returned. - /// The mapping from source element to key. - /// The equality comparer to use to determine whether or not keys are equal. - /// If null, the default equality comparer for TSource is used. - /// A sequence of elements from whose key was not also a key for - /// any element in . - - public static IEnumerable ExceptBy(this IEnumerable first, - IEnumerable second, - Func keySelector, - IEqualityComparer keyComparer) - => MoreEnumerable.ExceptBy(first, second, keySelector, keyComparer); - } + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + Func resultSelector) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, sixth, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7, T8)> EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, sixth, seventh, eighth); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + Func resultSelector) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, sixth, seventh, resultSelector); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. An exception is thrown + /// if the input sequences are of different lengths. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// The input sequences are of different lengths. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable EquiZip( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth, + Func resultSelector) + => MoreEnumerable.EquiZip(first, second, third, fourth, fifth, sixth, seventh, eighth, resultSelector); + + } + + /// Evaluate extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class EvaluateExtension + { + /// + /// Returns a sequence containing the values resulting from invoking (in order) each function in the source sequence of functions. + /// + /// + /// This operator uses deferred execution and streams the results. + /// If the resulting sequence is enumerated multiple times, the functions will be + /// evaluated multiple times too. + /// + /// The type of the object returned by the functions. + /// The functions to evaluate. + /// A sequence with results from invoking . + /// When is null. + + public static IEnumerable Evaluate(this IEnumerable> functions) => MoreEnumerable.Evaluate(functions); + + } + + /// Exactly extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class ExactlyExtension + { + + /// + /// Determines whether or not the number of elements in the sequence is equals to the given integer. + /// + /// Element type of sequence + /// The source sequence + /// The exactly number of items a sequence must have for this + /// function to return true + /// is null + /// is negative + /// true if the number of elements in the sequence is equals + /// to the given integer or false otherwise. + /// + /// + /// The result variable will contain true. + /// + + public static bool Exactly(this IEnumerable source, int count) + => MoreEnumerable.Exactly(source, count); + + } + + /// ExceptBy extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class ExceptByExtension + { + /// + /// Returns the set of elements in the first sequence which aren't + /// in the second sequence, according to a given key selector. + /// + /// + /// This is a set operation; if multiple elements in have + /// equal keys, only the first such element is returned. + /// This operator uses deferred execution and streams the results, although + /// a set of keys from is immediately selected and retained. + /// + /// The type of the elements in the input sequences. + /// The type of the key returned by . + /// The sequence of potentially included elements. + /// The sequence of elements whose keys may prevent elements in + /// from being returned. + /// The mapping from source element to key. + /// A sequence of elements from whose key was not also a key for + /// any element in . + + public static IEnumerable ExceptBy(this IEnumerable first, + IEnumerable second, + Func keySelector) + => MoreEnumerable.ExceptBy(first, second, keySelector); + + /// + /// Returns the set of elements in the first sequence which aren't + /// in the second sequence, according to a given key selector. + /// + /// + /// This is a set operation; if multiple elements in have + /// equal keys, only the first such element is returned. + /// This operator uses deferred execution and streams the results, although + /// a set of keys from is immediately selected and retained. + /// + /// The type of the elements in the input sequences. + /// The type of the key returned by . + /// The sequence of potentially included elements. + /// The sequence of elements whose keys may prevent elements in + /// from being returned. + /// The mapping from source element to key. + /// The equality comparer to use to determine whether or not keys are equal. + /// If null, the default equality comparer for TSource is used. + /// A sequence of elements from whose key was not also a key for + /// any element in . + + public static IEnumerable ExceptBy(this IEnumerable first, + IEnumerable second, + Func keySelector, + IEqualityComparer keyComparer) + => MoreEnumerable.ExceptBy(first, second, keySelector, keyComparer); + + } /// Exclude extension. @@ -6761,202 +7154,627 @@ public static IEnumerable> WindowRight(this IEnumerable< [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] public static partial class ZipLongestExtension { + /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence /// will always be as long as the longest of input sequences where the /// default value of each of the shorter sequence element types is used /// for padding. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// - /// Function to apply to each pair of elements. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// The first source sequence. + /// The second source sequence. /// - /// A sequence that contains elements of the two input sequences, - /// combined by . - /// - /// - /// n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield "1A", - /// "2B", "3C", "0D" in turn. - /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. /// /// This operator uses deferred execution and streams its results. /// - public static IEnumerable ZipLongest( - this IEnumerable first, - IEnumerable second, - Func resultSelector) - => MoreEnumerable.ZipLongest(first, second, resultSelector); + public static IEnumerable<(T1, T2)> ZipLongest( + this IEnumerable first, + IEnumerable second) + => MoreEnumerable.ZipLongest(first, second); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + public static IEnumerable<(T1, T2, T3)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third) + => MoreEnumerable.ZipLongest(first, second, third); /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence + /// element from each of the input sequences. The resulting sequence /// will always be as long as the longest of input sequences where the /// default value of each of the shorter sequence element types is used /// for padding. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// The third sequence. + /// The first source sequence. + /// The second source sequence. /// - /// Function to apply to each triplet of elements. + /// Function to apply to each tuple of elements. /// - /// A sequence that contains elements of the three input sequences, - /// combined by . - /// - /// - /// n + l + c); - /// ]]> - /// The zipped variable, when iterated over, will yield "1Aa", - /// "2Bb", "3Cc", "0Dd", "0e" in turn. - /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. /// /// This operator uses deferred execution and streams its results. /// - public static IEnumerable ZipLongest( + public static IEnumerable ZipLongest( this IEnumerable first, IEnumerable second, - IEnumerable third, - Func resultSelector) - => MoreEnumerable.ZipLongest(first, second, third, resultSelector); + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, resultSelector); /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence /// will always be as long as the longest of input sequences where the /// default value of each of the shorter sequence element types is used /// for padding. /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in third sequence - /// Type of elements in fourth sequence - /// Type of elements in result sequence - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// The fourth sequence. - /// - /// Function to apply to each quadruplet of elements. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. /// - /// A sequence that contains elements of the four input sequences, - /// combined by . - /// - /// - /// n + l + c + f); - /// ]]> - /// The zipped variable, when iterated over, will yield "1AaTrue", - /// "2BbFalse", "3CcTrue", "0DdFalse", "0eTrue", "0\0False" in turn. - /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. /// /// This operator uses deferred execution and streams its results. /// - public static IEnumerable ZipLongest( + public static IEnumerable<(T1, T2, T3, T4)> ZipLongest( this IEnumerable first, IEnumerable second, IEnumerable third, - IEnumerable fourth, - Func resultSelector) - => MoreEnumerable.ZipLongest(first, second, third, fourth, resultSelector); - - } - - /// ZipShortest extension. + IEnumerable fourth) + => MoreEnumerable.ZipLongest(first, second, third, fourth); - [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] - public static partial class ZipShortestExtension - { /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// is as short as the shortest input sequence. + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. /// - /// Function to apply to each pair of elements. + /// Function to apply to each tuple of elements. /// /// A projection of tuples, where each tuple contains the N-th element /// from each of the argument sequences. - /// - /// n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", in turn. - /// /// - /// - /// If the input sequences are of different lengths, the result sequence - /// is terminated as soon as the shortest input sequence is exhausted - /// and remainder elements from the longer sequences are never consumed. - /// - /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, third, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, third, fourth, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, sixth); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, sixth, seventh); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, sixth, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7, T8)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, sixth, seventh, eighth); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, sixth, seventh, resultSelector); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth, + Func resultSelector) + => MoreEnumerable.ZipLongest(first, second, third, fourth, fifth, sixth, seventh, eighth, resultSelector); + + } + + /// ZipShortest extension. + + [GeneratedCode("MoreLinq.ExtensionsGenerator", "1.0.0.0")] + public static partial class ZipShortestExtension + { + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// /// This operator uses deferred execution and streams its results. /// - public static IEnumerable ZipShortest( - this IEnumerable first, - IEnumerable second, - Func resultSelector) + public static IEnumerable<(T1, T2)> ZipShortest( + this IEnumerable first, + IEnumerable second) + => MoreEnumerable.ZipShortest(first, second); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third) + => MoreEnumerable.ZipShortest(first, second, third); + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + Func resultSelector) => MoreEnumerable.ZipShortest(first, second, resultSelector); + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth) + => MoreEnumerable.ZipShortest(first, second, third, fourth); + /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence + /// element from each of the input sequences. The resulting sequence /// is as short as the shortest input sequence. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. /// Type of elements in result sequence. - /// First sequence - /// Second sequence - /// Third sequence + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. /// - /// Function to apply to each triplet of elements. + /// Function to apply to each tuple of elements. /// /// A projection of tuples, where each tuple contains the N-th element /// from each of the argument sequences. - /// - /// c + n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield - /// "98A", "100B", "102C", in turn. - /// /// /// /// If the input sequences are of different lengths, the result sequence @@ -6974,36 +7792,61 @@ public static IEnumerable ZipShortest( Func resultSelector) => MoreEnumerable.ZipShortest(first, second, third, resultSelector); + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth); + /// /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence + /// element from each of the input sequences. The resulting sequence /// is as short as the shortest input sequence. /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. - /// Type of elements in fourth sequence. + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// The fourth sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. /// - /// Function to apply to each quadruplet of elements. + /// Function to apply to each tuple of elements. /// /// A projection of tuples, where each tuple contains the N-th element /// from each of the argument sequences. - /// - /// n + l + c + f); - /// ]]> - /// The zipped variable, when iterated over, will yield - /// "1AaTrue", "2BbFalse" in turn. - /// /// /// /// If the input sequences are of different lengths, the result sequence @@ -7022,5 +7865,309 @@ public static IEnumerable ZipShortest( Func resultSelector) => MoreEnumerable.ZipShortest(first, second, third, fourth, resultSelector); + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, sixth); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + Func resultSelector) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, sixth, seventh); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + Func resultSelector) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, sixth, resultSelector); + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7, T8)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, sixth, seventh, eighth); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + Func resultSelector) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, sixth, seventh, resultSelector); + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth, + Func resultSelector) + => MoreEnumerable.ZipShortest(first, second, third, fourth, fifth, sixth, seventh, eighth, resultSelector); + } } diff --git a/MoreLinq/MoreLinq.csproj b/MoreLinq/MoreLinq.csproj index 551c30fc1..9c27744f5 100644 --- a/MoreLinq/MoreLinq.csproj +++ b/MoreLinq/MoreLinq.csproj @@ -159,6 +159,10 @@ TextTemplatingFileGenerator Cartesian.g.cs + + TextTemplatingFileGenerator + EquiZip.g.cs + Aggregate.g.cs TextTemplatingFileGenerator @@ -171,6 +175,14 @@ TextTemplatingFileGenerator ToDelimitedString.g.cs + + TextTemplatingFileGenerator + ZipLongest.g.cs + + + TextTemplatingFileGenerator + ZipShortest.g.cs + @@ -212,6 +224,11 @@ True Cartesian.g.tt + + True + True + EquiZip.g.tt + True True @@ -235,6 +252,16 @@ True ToDelimitedString.g.tt + + True + True + ZipLongest.g.tt + + + True + True + ZipShortest.g.tt + diff --git a/MoreLinq/ZipImpl.cs b/MoreLinq/ZipImpl.cs deleted file mode 100644 index 2005660cb..000000000 --- a/MoreLinq/ZipImpl.cs +++ /dev/null @@ -1,97 +0,0 @@ -#region License and Terms -// MoreLINQ - Extensions to LINQ to Objects -// Copyright (c) 2018 Leandro F. Vieira (leandromoh). All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -namespace MoreLinq -{ - using System; - using System.Collections.Generic; - using System.Collections; - - static partial class MoreEnumerable - { - delegate TResult Folder(params T[] args); - - static IEnumerable ZipImpl( - IEnumerable s1, - IEnumerable s2, - IEnumerable s3, - IEnumerable s4, - Func resultSelector, - int limit, - Folder errorSelector = null) - { - IEnumerator e1 = null; - IEnumerator e2 = null; - IEnumerator e3 = null; - IEnumerator e4 = null; - var terminations = 0; - - try - { - e1 = s1 .GetEnumerator(); - e2 = s2 .GetEnumerator(); - e3 = s3?.GetEnumerator(); - e4 = s4?.GetEnumerator(); - - while (true) - { - var n = 0; - var v1 = Read(ref e1, ++n); - var v2 = Read(ref e2, ++n); - var v3 = Read(ref e3, ++n); - var v4 = Read(ref e4, ++n); - - if (terminations <= limit) - yield return resultSelector(v1, v2, v3, v4); - else - yield break; - } - } - finally - { - e1?.Dispose(); - e2?.Dispose(); - e3?.Dispose(); - e4?.Dispose(); - } - - T Read(ref IEnumerator e, int n) - { - if (e == null || terminations > limit) - return default; - - T value; - if (e.MoveNext()) - { - value = e.Current; - } - else - { - e.Dispose(); - e = null; - terminations++; - value = default; - } - - if (errorSelector != null && terminations > 0 && terminations < n) - throw errorSelector(e1, e2, e3, e4); - - return value; - } - } - } -} diff --git a/MoreLinq/ZipLongest.cs b/MoreLinq/ZipLongest.cs deleted file mode 100644 index ec5a240e6..000000000 --- a/MoreLinq/ZipLongest.cs +++ /dev/null @@ -1,169 +0,0 @@ -#region License and Terms -// MoreLINQ - Extensions to LINQ to Objects -// Copyright (c) 2008 Jonathan Skeet. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -namespace MoreLinq -{ - using System; - using System.Collections.Generic; - - static partial class MoreEnumerable - { - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// will always be as long as the longest of input sequences where the - /// default value of each of the shorter sequence element types is used - /// for padding. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// - /// Function to apply to each pair of elements. - /// - /// A sequence that contains elements of the two input sequences, - /// combined by . - /// - /// - /// n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield "1A", - /// "2B", "3C", "0D" in turn. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable ZipLongest( - this IEnumerable first, - IEnumerable second, - 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, c, d) => resultSelector(a, b), 1); - } - - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// will always be as long as the longest of input sequences where the - /// default value of each of the shorter sequence element types is used - /// for padding. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// - /// Function to apply to each triplet of elements. - /// - /// A sequence that contains elements of the three input sequences, - /// combined by . - /// - /// - /// n + l + c); - /// ]]> - /// The zipped variable, when iterated over, will yield "1Aa", - /// "2Bb", "3Cc", "0Dd", "0e" in turn. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable ZipLongest( - this IEnumerable first, - IEnumerable second, - IEnumerable third, - 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, d) => resultSelector(a, b, c), 2); - } - - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// will always be as long as the longest of input sequences where the - /// default value of each of the shorter sequence element types is used - /// for padding. - /// - /// Type of elements in first sequence - /// Type of elements in second sequence - /// Type of elements in third sequence - /// Type of elements in fourth sequence - /// Type of elements in result sequence - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// The fourth sequence. - /// - /// Function to apply to each quadruplet of elements. - /// - /// A sequence that contains elements of the four input sequences, - /// combined by . - /// - /// - /// n + l + c + f); - /// ]]> - /// The zipped variable, when iterated over, will yield "1AaTrue", - /// "2BbFalse", "3CcTrue", "0DdFalse", "0eTrue", "0\0False" in turn. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable ZipLongest( - this IEnumerable first, - IEnumerable second, - IEnumerable third, - IEnumerable fourth, - 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); - if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - - return ZipImpl(first, second, third, fourth, resultSelector, 3); - } - } -} diff --git a/MoreLinq/ZipLongest.g.cs b/MoreLinq/ZipLongest.g.cs new file mode 100644 index 000000000..a98be8cd9 --- /dev/null +++ b/MoreLinq/ZipLongest.g.cs @@ -0,0 +1,908 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + 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 _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2)) + { + yield return resultSelector(v1, v2); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2)> ZipLongest( + this IEnumerable first, + IEnumerable second) + { + return ZipLongest( + first, + second, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + 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 _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + IEnumerator e3 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + e3 = third.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + var v3 = default(T3); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2) | + ZipLongestHelper.MoveNextOrDispose(ref e3, ref v3)) + { + yield return resultSelector(v1, v2, v3); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + e3?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third) + { + return ZipLongest( + first, + second, + third, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + IEnumerator e3 = null; + IEnumerator e4 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + e3 = third.GetEnumerator(); + e4 = fourth.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + var v3 = default(T3); + var v4 = default(T4); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2) | + ZipLongestHelper.MoveNextOrDispose(ref e3, ref v3) | + ZipLongestHelper.MoveNextOrDispose(ref e4, ref v4)) + { + yield return resultSelector(v1, v2, v3, v4); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + e3?.Dispose(); + e4?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth) + { + return ZipLongest( + first, + second, + third, + fourth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + IEnumerator e3 = null; + IEnumerator e4 = null; + IEnumerator e5 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + e3 = third.GetEnumerator(); + e4 = fourth.GetEnumerator(); + e5 = fifth.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + var v3 = default(T3); + var v4 = default(T4); + var v5 = default(T5); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2) | + ZipLongestHelper.MoveNextOrDispose(ref e3, ref v3) | + ZipLongestHelper.MoveNextOrDispose(ref e4, ref v4) | + ZipLongestHelper.MoveNextOrDispose(ref e5, ref v5)) + { + yield return resultSelector(v1, v2, v3, v4, v5); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + e3?.Dispose(); + e4?.Dispose(); + e5?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth) + { + return ZipLongest( + first, + second, + third, + fourth, + fifth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + IEnumerator e3 = null; + IEnumerator e4 = null; + IEnumerator e5 = null; + IEnumerator e6 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + e3 = third.GetEnumerator(); + e4 = fourth.GetEnumerator(); + e5 = fifth.GetEnumerator(); + e6 = sixth.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + var v3 = default(T3); + var v4 = default(T4); + var v5 = default(T5); + var v6 = default(T6); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2) | + ZipLongestHelper.MoveNextOrDispose(ref e3, ref v3) | + ZipLongestHelper.MoveNextOrDispose(ref e4, ref v4) | + ZipLongestHelper.MoveNextOrDispose(ref e5, ref v5) | + ZipLongestHelper.MoveNextOrDispose(ref e6, ref v6)) + { + yield return resultSelector(v1, v2, v3, v4, v5, v6); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + e3?.Dispose(); + e4?.Dispose(); + e5?.Dispose(); + e6?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth) + { + return ZipLongest( + first, + second, + third, + fourth, + fifth, + sixth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (seventh == null) throw new ArgumentNullException(nameof(seventh)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + IEnumerator e3 = null; + IEnumerator e4 = null; + IEnumerator e5 = null; + IEnumerator e6 = null; + IEnumerator e7 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + e3 = third.GetEnumerator(); + e4 = fourth.GetEnumerator(); + e5 = fifth.GetEnumerator(); + e6 = sixth.GetEnumerator(); + e7 = seventh.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + var v3 = default(T3); + var v4 = default(T4); + var v5 = default(T5); + var v6 = default(T6); + var v7 = default(T7); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2) | + ZipLongestHelper.MoveNextOrDispose(ref e3, ref v3) | + ZipLongestHelper.MoveNextOrDispose(ref e4, ref v4) | + ZipLongestHelper.MoveNextOrDispose(ref e5, ref v5) | + ZipLongestHelper.MoveNextOrDispose(ref e6, ref v6) | + ZipLongestHelper.MoveNextOrDispose(ref e7, ref v7)) + { + yield return resultSelector(v1, v2, v3, v4, v5, v6, v7); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + e3?.Dispose(); + e4?.Dispose(); + e5?.Dispose(); + e6?.Dispose(); + e7?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh) + { + return ZipLongest( + first, + second, + third, + fourth, + fifth, + sixth, + seventh, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (seventh == null) throw new ArgumentNullException(nameof(seventh)); + if (eighth == null) throw new ArgumentNullException(nameof(eighth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + IEnumerator e1 = null; + IEnumerator e2 = null; + IEnumerator e3 = null; + IEnumerator e4 = null; + IEnumerator e5 = null; + IEnumerator e6 = null; + IEnumerator e7 = null; + IEnumerator e8 = null; + + try + { + e1 = first.GetEnumerator(); + e2 = second.GetEnumerator(); + e3 = third.GetEnumerator(); + e4 = fourth.GetEnumerator(); + e5 = fifth.GetEnumerator(); + e6 = sixth.GetEnumerator(); + e7 = seventh.GetEnumerator(); + e8 = eighth.GetEnumerator(); + + var v1 = default(T1); + var v2 = default(T2); + var v3 = default(T3); + var v4 = default(T4); + var v5 = default(T5); + var v6 = default(T6); + var v7 = default(T7); + var v8 = default(T8); + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( + ZipLongestHelper.MoveNextOrDispose(ref e1, ref v1) | + ZipLongestHelper.MoveNextOrDispose(ref e2, ref v2) | + ZipLongestHelper.MoveNextOrDispose(ref e3, ref v3) | + ZipLongestHelper.MoveNextOrDispose(ref e4, ref v4) | + ZipLongestHelper.MoveNextOrDispose(ref e5, ref v5) | + ZipLongestHelper.MoveNextOrDispose(ref e6, ref v6) | + ZipLongestHelper.MoveNextOrDispose(ref e7, ref v7) | + ZipLongestHelper.MoveNextOrDispose(ref e8, ref v8)) + { + yield return resultSelector(v1, v2, v3, v4, v5, v6, v7, v8); + } + } + finally + { + e1?.Dispose(); + e2?.Dispose(); + e3?.Dispose(); + e4?.Dispose(); + e5?.Dispose(); + e6?.Dispose(); + e7?.Dispose(); + e8?.Dispose(); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7, T8)> ZipLongest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth) + { + return ZipLongest( + first, + second, + third, + fourth, + fifth, + sixth, + seventh, + eighth, + ValueTuple.Create); + } + + } +} diff --git a/MoreLinq/ZipLongest.g.tt b/MoreLinq/ZipLongest.g.tt new file mode 100644 index 000000000..b45c1bebe --- /dev/null +++ b/MoreLinq/ZipLongest.g.tt @@ -0,0 +1,167 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="System.Collections" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Linq" #> +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +<# + var ordinals = new[] + { + "", + "first", "second", "third", "fourth", + "fifth", "sixth", "seventh", "eighth" + }; + + var overloads = + Enumerable.Range(2, 7) + .Select(argCount => + Enumerable.Range(1, argCount).Select(argPosition => + new + { + IsFirst = argPosition == 1, + IsLast = argPosition == argCount, + Name = ordinals[argPosition], + Ordinal = ordinals[argPosition], + Type = $"T{argPosition}", + // Objects associated with the argument + Enumerator = $"e{argPosition}", + Value = $"v{argPosition}" + })) + .Select(args => args.ToList()) + .Select(args => + new + { + Arguments = args, + TParams = string.Join(", ", args.Select(arg => arg.Type)) + }); +#> +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { +<# foreach (var o in overloads) + { +#> + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// +<# foreach (var arg in o.Arguments) { #> + /// Type of elements in <#=arg.Name#> input sequence. +<#} #> + /// Type of elements in result sequence. +<# foreach (var arg in o.Arguments) { #> + /// The <#=arg.Ordinal#> source sequence. +<#} #> + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipLongest<<#=o.TParams#>, TResult>( +<# foreach (var arg in o.Arguments) { #> + <#= arg.IsFirst ? "this " : "" #>IEnumerable<<#=arg.Type#>> <#=arg.Name#>, +<#}#> + Func<<#=o.TParams#>, TResult> resultSelector) + { +<# foreach (var arg in o.Arguments) { #> + if (<#=arg.Name#> == null) throw new ArgumentNullException(nameof(<#=arg.Name#>)); +<#} #> + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { +<# foreach (var arg in o.Arguments) { #> + IEnumerator<<#=arg.Type#>> <#=arg.Enumerator#> = null; +<#} #> + + try + { +<# foreach (var arg in o.Arguments) { #> + <#=arg.Enumerator#> = <#=arg.Name#>.GetEnumerator(); +<#} #> + +<# foreach (var arg in o.Arguments) { #> + var <#=arg.Value#> = default(<#=arg.Type#>); +<#} #> + + // | is used instead of || in purpose. All operands have to be evaluated. + while ( +<# foreach (var arg in o.Arguments) { #> + ZipLongestHelper.MoveNextOrDispose<<#=arg.Type#>>(ref <#=arg.Enumerator#>, ref <#=arg.Value#>)<#= arg.IsLast ? ")" : " |" #> +<#}#> + { + yield return resultSelector(<# foreach (var arg in o.Arguments) { #><#=arg.Value#><#= arg.IsLast ? "" : ", " #><#}#>); + } + } + finally + { +<# foreach (var arg in o.Arguments) { #> + <#=arg.Enumerator#>?.Dispose(); +<#} #> + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// will always be as long as the longest of input sequences where the + /// default value of each of the shorter sequence element types is used + /// for padding. + /// +<# foreach (var arg in o.Arguments) { #> + /// Type of elements in <#=arg.Name#> input sequence. +<#} #> +<# foreach (var arg in o.Arguments) { #> + /// The <#=arg.Ordinal#> source sequence. +<#} #> + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(<#=o.TParams#>)> ZipLongest<<#=o.TParams#>>( +<# foreach (var arg in o.Arguments) { #> + <#= arg.IsFirst ? "this " : "" #>IEnumerable<<#=arg.Type#>> <#=arg.Name#><#= arg.IsLast ? ")" : "," #> +<#}#> + { + return ZipLongest( +<# foreach (var arg in o.Arguments) { #> + <#=arg.Name#>, +<#}#> + ValueTuple.Create); + } + +<# } #> + } +} diff --git a/MoreLinq/ZipLongestHelper.cs b/MoreLinq/ZipLongestHelper.cs new file mode 100644 index 000000000..09676eb0d --- /dev/null +++ b/MoreLinq/ZipLongestHelper.cs @@ -0,0 +1,63 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System.Collections.Generic; + + static class ZipLongestHelper + { + /// + /// Move the to the next position and put the + /// new current value into . + /// + /// If the has no more element it's disposed and + /// set to null, and is set to default. + /// + /// If the is null the method return immediately + /// and is not modified. + /// + /// The type of element that are enumerated. + /// The enumerator to iterate or dispose. + /// The new current value of or + /// default if has no more element. + /// + /// + /// Because and may both be modified + /// they are both passed by reference. + /// + /// A bool value indicating if the enumerator has moved to the next element. + public static bool MoveNextOrDispose(ref IEnumerator enumerator, ref T value) + { + if (enumerator == null) + { + return false; + } + + if (enumerator.MoveNext()) + { + value = enumerator.Current; + return true; + } + + enumerator.Dispose(); + enumerator = null; + value = default; + return false; + } + } +} diff --git a/MoreLinq/ZipShortest.cs b/MoreLinq/ZipShortest.cs deleted file mode 100644 index 06920e2df..000000000 --- a/MoreLinq/ZipShortest.cs +++ /dev/null @@ -1,185 +0,0 @@ -#region License and Terms -// MoreLINQ - Extensions to LINQ to Objects -// Copyright (c) 2008 Jonathan Skeet. All rights reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -#endregion - -namespace MoreLinq -{ - using System; - using System.Collections.Generic; - - static partial class MoreEnumerable - { - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// is as short as the shortest input sequence. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// - /// Function to apply to each pair of elements. - /// - /// A projection of tuples, where each tuple contains the N-th element - /// from each of the argument sequences. - /// - /// n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield "1A", "2B", "3C", in turn. - /// - /// - /// - /// If the input sequences are of different lengths, the result sequence - /// is terminated as soon as the shortest input sequence is exhausted - /// and remainder elements from the longer sequences are never consumed. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable ZipShortest( - this IEnumerable first, - IEnumerable second, - 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, c, d) => resultSelector(a, b)); - } - - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// is as short as the shortest input sequence. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. - /// Type of elements in result sequence. - /// First sequence - /// Second sequence - /// Third sequence - /// - /// Function to apply to each triplet of elements. - /// - /// A projection of tuples, where each tuple contains the N-th element - /// from each of the argument sequences. - /// - /// c + n + l); - /// ]]> - /// The zipped variable, when iterated over, will yield - /// "98A", "100B", "102C", in turn. - /// - /// - /// - /// If the input sequences are of different lengths, the result sequence - /// is terminated as soon as the shortest input sequence is exhausted - /// and remainder elements from the longer sequences are never consumed. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable ZipShortest( - this IEnumerable first, - IEnumerable second, - IEnumerable third, - 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)); - } - - /// - /// Returns a projection of tuples, where each tuple contains the N-th - /// element from each of the argument sequences. The resulting sequence - /// is as short as the shortest input sequence. - /// - /// Type of elements in first sequence. - /// Type of elements in second sequence. - /// Type of elements in third sequence. - /// Type of elements in fourth sequence. - /// Type of elements in result sequence. - /// The first sequence. - /// The second sequence. - /// The third sequence. - /// The fourth sequence. - /// - /// Function to apply to each quadruplet of elements. - /// - /// A projection of tuples, where each tuple contains the N-th element - /// from each of the argument sequences. - /// - /// n + l + c + f); - /// ]]> - /// The zipped variable, when iterated over, will yield - /// "1AaTrue", "2BbFalse" in turn. - /// - /// - /// - /// If the input sequences are of different lengths, the result sequence - /// is terminated as soon as the shortest input sequence is exhausted - /// and remainder elements from the longer sequences are never consumed. - /// - /// - /// This operator uses deferred execution and streams its results. - /// - - public static IEnumerable ZipShortest( - this IEnumerable first, - IEnumerable second, - IEnumerable third, - IEnumerable fourth, - 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); - if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); - - return ZipImpl(first, second, third, fourth, resultSelector); - } - - static IEnumerable ZipImpl( - IEnumerable s1, IEnumerable s2, - IEnumerable s3, IEnumerable s4, - Func resultSelector) - { - return ZipImpl(s1, s2, s3, s4, resultSelector, 0); - } - } -} diff --git a/MoreLinq/ZipShortest.g.cs b/MoreLinq/ZipShortest.g.cs new file mode 100644 index 000000000..374f28cc2 --- /dev/null +++ b/MoreLinq/ZipShortest.g.cs @@ -0,0 +1,761 @@ +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + 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 _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// The first source sequence. + /// The second source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2)> ZipShortest( + this IEnumerable first, + IEnumerable second) + { + return ZipShortest( + first, + second, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + 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 _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current, e3.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third) + { + return ZipShortest( + first, + second, + third, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth) + { + return ZipShortest( + first, + second, + third, + fourth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth) + { + return ZipShortest( + first, + second, + third, + fourth, + fifth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + using var e6 = sixth.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext() && e6.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current, e6.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth) + { + return ZipShortest( + first, + second, + third, + fourth, + fifth, + sixth, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (seventh == null) throw new ArgumentNullException(nameof(seventh)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + using var e6 = sixth.GetEnumerator(); + using var e7 = seventh.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext() && e6.MoveNext() && e7.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current, e6.Current, e7.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh) + { + return ZipShortest( + first, + second, + third, + fourth, + fifth, + sixth, + seventh, + ValueTuple.Create); + } + + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// Type of elements in result sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth, + 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 (fourth == null) throw new ArgumentNullException(nameof(fourth)); + if (fifth == null) throw new ArgumentNullException(nameof(fifth)); + if (sixth == null) throw new ArgumentNullException(nameof(sixth)); + if (seventh == null) throw new ArgumentNullException(nameof(seventh)); + if (eighth == null) throw new ArgumentNullException(nameof(eighth)); + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { + using var e1 = first.GetEnumerator(); + using var e2 = second.GetEnumerator(); + using var e3 = third.GetEnumerator(); + using var e4 = fourth.GetEnumerator(); + using var e5 = fifth.GetEnumerator(); + using var e6 = sixth.GetEnumerator(); + using var e7 = seventh.GetEnumerator(); + using var e8 = eighth.GetEnumerator(); + + while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext() && e4.MoveNext() && e5.MoveNext() && e6.MoveNext() && e7.MoveNext() && e8.MoveNext()) + { + yield return resultSelector(e1.Current, e2.Current, e3.Current, e4.Current, e5.Current, e6.Current, e7.Current, e8.Current); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// + /// Type of elements in first input sequence. + /// Type of elements in second input sequence. + /// Type of elements in third input sequence. + /// Type of elements in fourth input sequence. + /// Type of elements in fifth input sequence. + /// Type of elements in sixth input sequence. + /// Type of elements in seventh input sequence. + /// Type of elements in eighth input sequence. + /// The first source sequence. + /// The second source sequence. + /// The third source sequence. + /// The fourth source sequence. + /// The fifth source sequence. + /// The sixth source sequence. + /// The seventh source sequence. + /// The eighth source sequence. + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(T1, T2, T3, T4, T5, T6, T7, T8)> ZipShortest( + this IEnumerable first, + IEnumerable second, + IEnumerable third, + IEnumerable fourth, + IEnumerable fifth, + IEnumerable sixth, + IEnumerable seventh, + IEnumerable eighth) + { + return ZipShortest( + first, + second, + third, + fourth, + fifth, + sixth, + seventh, + eighth, + ValueTuple.Create); + } + + } +} diff --git a/MoreLinq/ZipShortest.g.tt b/MoreLinq/ZipShortest.g.tt new file mode 100644 index 000000000..d23f6cc97 --- /dev/null +++ b/MoreLinq/ZipShortest.g.tt @@ -0,0 +1,154 @@ +<#@ template debug="false" hostspecific="false" language="C#" #> +<#@ output extension=".cs" #> +<#@ assembly name="System.Core" #> +<#@ assembly name="System.Collections" #> +<#@ import namespace="System.Globalization" #> +<#@ import namespace="System.Linq" #> +#region License and Terms +// MoreLINQ - Extensions to LINQ to Objects +// Copyright (c) 2019 Pierre Lando. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#endregion + +<# + var ordinals = new[] + { + "", + "first", "second", "third", "fourth", + "fifth", "sixth", "seventh", "eighth" + }; + + var overloads = + Enumerable.Range(2, 7) + .Select(argCount => + Enumerable.Range(1, argCount).Select(argPosition => + new + { + IsFirst = argPosition == 1, + IsLast = argPosition == argCount, + Name = ordinals[argPosition], + Ordinal = ordinals[argPosition], + Type = $"T{argPosition}", + // Objects associated with the argument + Enumerator = $"e{argPosition}", + Value = $"v{argPosition}" + })) + .Select(args => args.ToList()) + .Select(args => + new + { + Arguments = args, + TParams = string.Join(", ", args.Select(arg => arg.Type)) + }); +#> +namespace MoreLinq +{ + using System; + using System.Collections.Generic; + + static partial class MoreEnumerable + { +<# foreach (var o in overloads) + { +#> + /// + /// Returns a projection of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// +<# foreach (var arg in o.Arguments) { #> + /// Type of elements in <#=arg.Name#> input sequence. +<#} #> + /// Type of elements in result sequence. +<# foreach (var arg in o.Arguments) { #> + /// The <#=arg.Ordinal#> source sequence. +<#} #> + /// + /// Function to apply to each tuple of elements. + /// + /// A projection of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable ZipShortest<<#=o.TParams#>, TResult>( +<# foreach (var arg in o.Arguments) { #> + <#= arg.IsFirst ? "this " : "" #>IEnumerable<<#=arg.Type#>> <#=arg.Name#>, +<#}#> + Func<<#=o.TParams#>, TResult> resultSelector) + { +<# foreach (var arg in o.Arguments) { #> + if (<#=arg.Name#> == null) throw new ArgumentNullException(nameof(<#=arg.Name#>)); +<#} #> + if (resultSelector == null) throw new ArgumentNullException(nameof(resultSelector)); + + return _(); IEnumerable _() + { +<# foreach (var arg in o.Arguments) { #> + using var <#=arg.Enumerator#> = <#=arg.Name#>.GetEnumerator(); +<#} #> + + while (<# foreach (var arg in o.Arguments) { #><#=arg.Enumerator#>.MoveNext()<#= arg.IsLast ? "" : " && " #><#}#>) + { + yield return resultSelector(<# foreach (var arg in o.Arguments) { #><#=arg.Enumerator#>.Current<#= arg.IsLast ? "" : ", " #><#}#>); + } + } + } + + /// + /// Returns a sequence of tuples, where each tuple contains the N-th + /// element from each of the input sequences. The resulting sequence + /// is as short as the shortest input sequence. + /// +<# foreach (var arg in o.Arguments) { #> + /// Type of elements in <#=arg.Name#> input sequence. +<#} #> +<# foreach (var arg in o.Arguments) { #> + /// The <#=arg.Ordinal#> source sequence. +<#} #> + /// + /// A sequence of tuples, where each tuple contains the N-th element + /// from each of the argument sequences. + /// + /// + /// If the input sequences are of different lengths, the result sequence + /// is terminated as soon as the shortest input sequence is exhausted + /// and remainder elements from the longer sequences are never consumed. + /// + /// + /// This operator uses deferred execution and streams its results. + /// + + public static IEnumerable<(<#=o.TParams#>)> ZipShortest<<#=o.TParams#>>( +<# foreach (var arg in o.Arguments) { #> + <#= arg.IsFirst ? "this " : "" #>IEnumerable<<#=arg.Type#>> <#=arg.Name#><#= arg.IsLast ? ")" : "," #> +<#}#> + { + return ZipShortest( +<# foreach (var arg in o.Arguments) { #> + <#=arg.Name#>, +<#}#> + ValueTuple.Create); + } + +<# } #> + } +} diff --git a/README.md b/README.md index d6923b81d..e643b9193 100644 --- a/README.md +++ b/README.md @@ -222,7 +222,7 @@ Returns a projection of tuples, where each tuple contains the N-th element from each of the argument sequences. An exception is thrown if the input sequences are of different lengths. -This method has 3 overloads. +This method has 14 overloads. ### Exactly @@ -717,7 +717,7 @@ will always be as long as the longest of input sequences where the default value of each of the shorter sequence element types is used for padding. -This method has 3 overloads. +This method has 14 overloads. ### ZipShortest @@ -725,7 +725,7 @@ Returns a projection of tuples, where each tuple contains the N-th element from each of the argument sequences. The resulting sequence is as short as the shortest input sequence. -This method has 3 overloads. +This method has 14 overloads. ## Experimental Operators