2015-09-23 90 views
3

我想弄清楚是否有内置的支持来压缩两个不同长度的IEnumerables,而不会丢失C#中较大列表中的元素。C#相当于python itertools.izip_longest

本质上,我在C#中寻找来自itertools的Python(> = 2.6)izip_longest版本。

我也开放给其他漂亮的定制解决方案使用LINQ获得相同的功能。为了说明更多,

如果a = [1, 2, 3]b = [4, 5, 6, 7]所需的输出应该是[[1, 4], [2, 5], [3, 6], [7]]

回答

4

我写了走IEnumerable<T>在一个自己的zip扩展方法:

public static IEnumerable<T[]> Zip<T>(this IEnumerable<T> left, IEnumerable<T> right) 
{ 
    IEnumerator<T> leftEnumerator = left.GetEnumerator(); 
    IEnumerator<T> rightEnumerator = right.GetEnumerator(); 

    bool hasLeft = leftEnumerator.MoveNext(); 
    bool hasRight = rightEnumerator.MoveNext(); 

    while (hasLeft || hasRight) 
    { 
     if (hasLeft && hasRight) 
     { 
      yield return new T[] { leftEnumerator.Current, rightEnumerator.Current }; 
     } 
     else if (hasLeft) 
     { 
      yield return new T[] { leftEnumerator.Current }; 
     } 
     else if (hasRight) 
     { 
      yield return new T[] { rightEnumerator.Current }; 
     } 

     hasLeft = leftEnumerator.MoveNext(); 
     hasRight = rightEnumerator.MoveNext(); 
    } 
} 

你可以这样调用:

int[] a = new int[] { 1, 2, 3 }; 
int[] b = new int[] { 4, 5, 6, 7 }; 

IEnumerable<int[]> zipped = a.Zip(b); 
4

LINQ本身有一个Zip方法与组合元素来回m两个序列并对它们应用一个函数(可以简单地将这些元素组合到一对)。结果是尽可能短的序列。

的MoreLINQ库增加了一些扩展LINQ包括像MaxByExceptBy和各种strategies for Zip方法,包括返回最短(邮编),最长(ZipLongest)或失败的错配(EquiZip)。

从文档的例子显示ZipLongest将返回默认值缺失的元素:

int[] numbers = { 1, 2, 3 }; 
string[] letters = { "A", "B", "C", "D" }; 
var zipped = numbers.ZipLongest(letters, (n, l) => n + l); 
/// ... will yield "1A", "2B", "3C", "0D" in turn. 

您可以从Nuget下载个体经营者(如ZipLongest)代码或二进制包,或者你可以下载整个图书馆的binary package