使用Zip()合并不同长度的数组而不会丢失值

在下面的代码中,我正在合并两个类型为intstring数组。 第一个的长度大于第二个长度,因此,最后一个索引(即5 )不会合并:

 int[] numbers = new[] { 1, 2, 3, 4, 5 }; string[] words = new string[] { "one", "two", "three", "four" }; var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w }); foreach (var nw in numbersAndWords) { Console.WriteLine(nw.Number + nw.Word); } 

我想知道一种让它合并的方法。 例如,在words中存在的最后一个字符串之后创建一个空字符串或空字符串,并使用它与最后一个numbers索引合并。 无法弄清楚。

编辑:我得到的结果

 1one 2two 3three 4four 

结果我想要

 1one 2two 3three 4four 5 

谢谢!

编辑:不重复,我的另一个问题是关于在null对象上调用方法。

您可以轻松编写自己的LINQ类扩展方法来执行此操作:

 public static class MyEnumerable { public static IEnumerable ZipWithDefault(this IEnumerable first, IEnumerable second, Func selector) { bool firstMoveNext, secondMoveNext; using (var enum1 = first.GetEnumerator()) using (var enum2 = second.GetEnumerator()) { while ((firstMoveNext = enum1.MoveNext()) & (secondMoveNext = enum2.MoveNext())) yield return selector(enum1.Current, enum2.Current); if (firstMoveNext && !secondMoveNext) { yield return selector(enum1.Current, default(TSecond)); while (enum1.MoveNext()) { yield return selector(enum1.Current, default(TSecond)); } } else if (!firstMoveNext && secondMoveNext) { yield return selector(default(TFirst), enum2.Current); while (enum2.MoveNext()) { yield return selector(default(TFirst), enum2.Current); } } } } } 

但是如果你的源始终是一对数组,那么简单地使用for循环可能更容易:

 public static IEnumerable ZipWithDefault(this TFirst[] first, TSecond[] second, Func selector) { var maxLength = Math.Max(first.Length, second.Length); for(var i = 0; i < maxLength; i++) { var firstItem = i < first.Length ? first[i] : default(TFirst); var secondItem = i < second.Length ? second[i] : default(TSecond); yield return selector(firstItem, secondItem); } } 

您可以在压缩它们之前扩展两个集合中较小的一个,例如:

 int[] numbers = new[] { 1, 2, 3, 4, 5 }; string[] words = new string[] { "one", "two", "three", "four" }; IEnumerable wordsExtended = words; if(words.Length < numbers.Length) { wordsExtended = words.Concat(Enumerable.Repeat("", numbers.Length - words.Length)); } var numbersAndWords = numbers.Zip(wordsExtended, (n, w) => new { Number = n, Word = w }); foreach (var nw in numbersAndWords) { Console.WriteLine(nw.Number + nw.Word); } 

理想情况下,您希望将其包装在实用程序方法中并且是通用的,因此它适用于任何压缩的集合。

看起来有人在这个程序员StackExchange答案上已经编写了一个通用实现。