如何以这样的方式2分集组合,所得集合包含的值替代地从两个集合合并2个集合
实施例: - 柱A = [1,2,3,4] 色柱B = [5,6,7,8]
结果山口C = [1,5,2,6,3,7,4,8]
如何以这样的方式2分集组合,所得集合包含的值替代地从两个集合合并2个集合
实施例: - 柱A = [1,2,3,4] 色柱B = [5,6,7,8]
结果山口C = [1,5,2,6,3,7,4,8]
有很多方法可以做到这一点,具体取决于输入类型和所需输出类型。然而,我没有意识到图书馆的方法。你必须“滚动你自己的”。
一种可能性将是一个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;
}
}
谢谢。只是为了好奇我们可以在LINUX中实现ZIP运算符吗?这是.NET 4.0的新手段来解决问题吗? – praveen 2012-03-22 03:21:46
@praveen Anthony Pegram的回答使用zip,但他似乎删除了它。这不是最有效的执行,但它确实使代码更简单。问题在于它会截断更长的序列,因此如果分别使用4项和5项输入集合,则输出将有8个项目,并且会丢失第二个集合中的最后一项。这可能是为什么安东尼删除了他的答案。 – phoog 2012-03-22 03:28:32
谢谢@phoog的澄清 – praveen 2012-03-22 03:34:53
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]
谢谢它解决了我的问题。 – praveen 2012-03-22 03:19:42
使用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
“包含值交替地”,因此A的索引0仍然存在,B的索引0在新数组中为1等。 – Lander 2012-03-22 02:58:43
假设两个集合长度相等的:
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));
如果集合不一定具有相同的长度,可以考虑扩展方法:
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();
如果在收到错误的返回值后调用MoveNext,许多枚举器将引发异常。这个答案不能防止这种情况发生。 – phoog 2012-03-22 03:11:14
这不是文档所说的,我没有看到至少对于常规集合(工作得很好) - 为这种行为举个例子? (docs say **当枚举器在这个位置时,对MoveNext的后续调用也会返回false,直到调用Reset为止。**) – BrokenGlass 2012-03-22 03:14:19
不,现在我发布了这个,我找不到任何支持证据。我确信我以前见过它。也许这是由没有阅读过文档的人编写的专有代码。 – phoog 2012-03-22 03:18:34
请问收藏始终是相同的长度? – Lander 2012-03-22 02:54:00
集合A和B的类型是什么?结果集合C具有什么类型? – phoog 2012-03-22 02:55:28
收集的数据类型可以是任何东西,长度可能不同 – praveen 2012-03-22 03:07:00