我有两个不同长度的List。我想要实现的是第三个List,其中包含list1中的第一个元素,然后是list2中的第一个元素,然后是list1中的第二个元素,以及list2中的第二个元素,依此类推,直到其中一个元素用尽(它们为止) “不均匀”,然后只需添加该列表中的任何剩余项目。
结果应该与list1和list2组合使用相同数量的项目。
我不能使用类似Union.ToList()的东西,因为它没有交织两者,它只是将例如list1中的所有项目添加到list2的底部并输出结果。我试过.Zip(Linq)然而,似乎接受了两个元素并将它们合并为一个元素(即将两个字符串连接成一个更长的字符串)。
List<string> list1 = new List<string>(){
"4041",
"4040"
};
List<string> list2 = new List<string>(){
"4039",
"4044",
"4075",
"4010",
"4100",
"4070",
"4072"
};
// Ideal result:
result = { "4041",
"4039",
"4040"
"4044",
"4075",
"4010",
"4100",
"4070",
"4072"
};
答案 0 :(得分:5)
int length = Math.Min(list1.Count, list2.Count);
// Combine the first 'length' elements from both lists into pairs
list1.Take(length)
.Zip(list2.Take(length), (a, b) => new int[] { a, b })
// Flatten out the pairs
.SelectMany(array => array)
// Concatenate the remaining elements in the lists)
.Concat(list1.Skip(length))
.Concat(list2.Skip(length));
答案 1 :(得分:2)
如果您不需要保持原始列表的完整性,您可以使用while循环来弹出每个列表前面的项目:
while(list1.Count > 0 || list2.Count > 0)
{
if(list1.Count > 0)
{
combinedList.Add(list1[0]);
list1.RemoveAt(0);
}
if(list2.Count > 0)
{
combinedList.Add(list2[0]);
list2.RemoveAt(0);
}
}
不像Linq那样简洁,但易于阅读并且非常清楚发生了什么。
答案 2 :(得分:1)
更长但可能更有效
List<string> result = new List<string>();
using (var enumerator1 = list1.GetEnumerator())
using (var enumerator2 = list2.GetEnumerator())
{
int countBefore;
do
{
countBefore = result.Count;
if (enumerator1.MoveNext())
result.Add(enumerator1.Current);
if (enumerator2.MoveNext())
result.Add(enumerator2.Current);
} while (countBefore < result.Count);
}
答案 3 :(得分:0)
我认为你正在寻找这样的东西:
list1
.SelectMany((x,idx) => new[] { x, list2[idx] })
.Concat(list2.Skip(list1.Count));
答案 4 :(得分:0)
我的看法,允许可变数量的 IEnumerables 交错
public static IEnumerable<T> Interleave<T>(params IEnumerable<T>[] enumerables)
{
var enumerators = enumerables.Select(e => e.GetEnumerator()).ToList();
while (enumerators.Any())
{
enumerators.RemoveAll(e => {
var ended = !e.MoveNext();
if (ended) e.Dispose();
return ended;
});
foreach (var enumerator in enumerators)
yield return enumerator.Current;
}
}