2012-03-22 172 views
1

如何以這樣的方式2分集組合,所得集合包含的值替代地從兩個集合合併2個集合

實施例: - 柱A = [1,2,3,4] 色柱B = [5,6,7,8]

結果山口C = [1,5,2,6,3,7,4,8]

+3

請問收藏始終是相同的長度? – Lander 2012-03-22 02:54:00

+0

集合A和B的類型是什麼?結果集合C具有什麼類型? – phoog 2012-03-22 02:55:28

+0

收集的數據類型可以是任何東西,長度可能不同 – praveen 2012-03-22 03:07:00

回答

2

有很多方法可以做到這一點,具體取決於輸入類型和所需輸出類型。然而,我沒有意識到圖書館的方法。你必須「滾動你自己的」。

一種可能性將是一個LINQ風格的迭代方法,假設我們只知道輸入的集合是他們實現IEnumerable<T>

static IEnumerable<T> Interleave(this IEnumerable<T> a, IEnumerable<T> b) 
{ 
    bool bEmpty = false; 
    using (var enumeratorB b.GetEnumerator()) 
    { 
     foreach (var elementA in a) 
     { 
      yield return elementA; 
      if (!bEmpty && bEnumerator.MoveNext()) 
       yield return bEnumerator.Current; 
      else 
       bEmpty = true; 
     } 
     if (!bEmpty) 
      while (bEnumerator.MoveNext()) 
       yield return bEnumerator.Current; 
    } 
} 
+0

謝謝。只是爲了好奇我們可以在LINUX中實現ZIP運算符嗎?這是.NET 4.0的新手段來解決問題嗎? – praveen 2012-03-22 03:21:46

+0

@praveen Anthony Pegram的回答使用zip,但他似乎刪除了它。這不是最有效的執行,但它確實使代碼更簡單。問題在於它會截斷更長的序列,因此如果分別使用4項和5項輸入集合,則輸出將有8個項目,並且會丟失第二個集合中的最後一項。這可能是爲什麼安東尼刪除了他的答案。 – phoog 2012-03-22 03:28:32

+0

謝謝@phoog的澄清 – praveen 2012-03-22 03:34:53

2
int[] a = { 1, 2, 3, 4 }; 
int[] b = { 5, 6, 7, 8 }; 
int[] result = a.SelectMany((n, index) => new[] { n, b[index] }).ToArray(); 

如果集合A和b都沒有同樣的長度,你需要小心使用b[index],也許你需要:index >= b.Length ? 0 : b[index]

+0

謝謝它解決了我的問題。 – praveen 2012-03-22 03:19:42

-2

使用LINQ的聯盟擴展名,例如:

var colA = new List<int> { 1, 2, 3, 4 }; 
var colB = new List<int> { 1, 5, 2, 6, 3, 7, 4, 8}; 

var result = colA.Union(colB); // 1, 2, 3, 4, 5, 6, 7, 8 
+3

「包含值交替地」,因此A的索引0仍然存在,B的索引0在新數組中爲1等。 – Lander 2012-03-22 02:58:43

1

假設兩個集合長度相等的:

Debug.Assert(a.Count == b.Count); 

for (int i = 0; i < a.Count; i++) 
{ 
    c.Add(a[i]); 
    c.Add(b[i]); 
} 

Debug.Assert(c.Count == (a.Count + b.Count)); 
2

如果集合不一定具有相同的長度,可以考慮擴展方法:

public static IEnumerable<T> AlternateMerge<T>(this IEnumerable<T> source, 
               IEnumerable<T> other) 
{ 
    using(var sourceEnumerator = source.GetEnumerator()) 
    using(var otherEnumerator = other.GetEnumerator()) 
    { 
     bool haveItemsSource = true; 
     bool haveItemsOther = true; 
     while (haveItemsSource || haveItemsOther) 
     { 
      haveItemsSource = sourceEnumerator.MoveNext(); 
      haveItemsOther = otherEnumerator.MoveNext(); 

      if (haveItemsSource) 
       yield return sourceEnumerator.Current; 

      if (haveItemsOther) 
       yield return otherEnumerator.Current; 
     } 
    } 
} 

並使用:

List<int> A = new List<int> { 1, 2, 3 }; 
List<int> B = new List<int> { 5, 6, 7, 8 }; 

var mergedList = A.AlternateMerge(B).ToList(); 
+0

如果在收到錯誤的返回值後調用MoveNext,許多枚舉器將引發異常。這個答案不能防止這種情況發生。 – phoog 2012-03-22 03:11:14

+1

這不是文檔所說的,我沒有看到至少對於常規集合(工作得很好) - 爲這種行爲舉個例子? (docs say **當枚舉器在這個位置時,對MoveNext的後續調用也會返回false,直到調用Reset爲止。**) – BrokenGlass 2012-03-22 03:14:19

+0

不,現在我發佈了這個,我找不到任何支持證據。我確信我以前見過它。也許這是由沒有閱讀過文檔的人編寫的專有代碼。 – phoog 2012-03-22 03:18:34