2015-09-23 89 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