2012-03-22 108 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