在c#中添加两个不同长度的列表

List a = new List{1,2,3}; List b = new List{1,2,3,4,5}; 

a + b应该给我2,4,6,4,5

显然我可以写一个循环,但有更好的方法吗? 用linq?

您可以轻松地使用修改后的“zip”操作,但内置任何内容。例如:

  static void Main() { var a = new List { 1, 2, 3 }; var b = new List { 1, 2, 3, 4, 5 }; foreach (var c in a.Merge(b, (x, y) => x + y)) { Console.WriteLine(c); } } static IEnumerable Merge(this IEnumerable first, IEnumerable second, Func operation) { using (var iter1 = first.GetEnumerator()) using (var iter2 = second.GetEnumerator()) { while (iter1.MoveNext()) { if (iter2.MoveNext()) { yield return operation(iter1.Current, iter2.Current); } else { yield return iter1.Current; } } while (iter2.MoveNext()) { yield return iter2.Current; } } } 

使用.NET 4.0的Zip运算符:

 var sums = b.Zip(a, (x, y) => x + y) .Concat(b.Skip(a.Count())); 

如果你想概括一下,检查哪个有更多的元素,并将其用作上面的“b”。

 Enumerable.Range(0, new[] { a.Count, b.Count }.Max()) .Select(n => a.ElementAtOrDefault(n) + b.ElementAtOrDefault(n)); 

我不得不稍微调整Marc的解决方案以供我使用以允许不同类型的列表,所以我想我会在其他任何人需要它的情况下发布。

 public static IEnumerable Merge(this IEnumerable first, IEnumerable second, Func operation) { using (var iter1 = first.GetEnumerator()) { using (var iter2 = second.GetEnumerator()) { while (iter1.MoveNext()) { if (iter2.MoveNext()) { yield return operation(iter1.Current, iter2.Current); } else { yield return operation(iter1.Current, default(TSecond)); } } while (iter2.MoveNext()) { yield return operation(default(TFirst), iter2.Current); } } } } 

这个怎么样:

 List doubles = Enumerable.Range(0, Math.Max(a.Count, b.Count)) .Select(x => (a.Count > x ? a[x] : 0) + (b.Count > x ? b[x] : 0)) .ToList(); 

以下是您的问题的解决方案。

 List a = new List{1,2,3}; List b = new List{1,2,3,4,5}; List sum = new List(); int max = Math.Min(a.Count, b.Count); for (int i = 0; i < max; i++){ sum.Add(a[i] + b[i]); } if (a.Count < b.Count) for (int i = max i < b.Count) sum.Add(b[i]); else for (int i = max i < a.Count) sum.Add(a[i]); 

丑陋的LINQ解决方案:

 var sum = Enumerable.Range(0, (a.Count > b.Count) ? a.Count : b.Count) .Select(i => (a.Count > i && b.Count > i) ? a[i] + b[i] : (a.Count > i) ? a[i] : b[i]); 

在这种情况下,无论列表是长度相同还是长度不同,都无关紧要。 .NET类库没有Enumerable.Zip方法来组合两个序列(它只会出现在.NET 4.0中),你可能需要这样的方法。 所以你要么必须编写循环,要么编写自己的Zip (这仍然涉及循环)。

有一些黑客可以在没有循环的单个LINQ查询中挤压这一切,包括加入索引,但那些会非常慢而且毫无意义。

123什么? 如果您正在寻找不同的价值观:

 var one = new List { 1, 2, 3 }; var two = new List { 1, 2, 3, 4, 5 }; foreach (var x in one.Union(two)) Console.Write("{0} ", x); 

会给你1 2 3 4 5

如果您正在寻找附加到第一个列表的第二个列表,那么:

 foreach(var x in one.Concat(two)) // ... 

会给你1 2 3 1 2 3 4 5

编辑 :哦,我明白了,你正在寻找一种Zip ,但它会返回额外的部分。 试试这个:

 public static IEnumerable Zip( this IEnumerable one, IEnumerable two, Func f) { using (var oneIter = one.GetEnumerator()) { using (var twoIter = two.GetEnumerator()) { while (oneIter.MoveNext()) { twoIter.MoveNext(); yield return f(oneIter.Current, twoIter.MoveNext() ? twoIter.Current : default(U)); } while (twoIter.MoveNext()) { yield return f(oneIter.Current, twoIter.Current); } } } } 

这里有一个更像普通的zip函数,它不会返回额外内容:

 public static IEnumerable Zip( this IEnumerable one, IEnumerable two, Func f) { using (var oneIter = one.GetEnumerator()) { using (var twoIter = two.GetEnumerator()) { while (oneIter.MoveNext()) { yield return f(oneIter.Current, twoIter.MoveNext() ? twoIter.Current : default(U)); } } } } 

用法示例:

 var one = new List { 1, 2, 3, 4, 5}; var two = new List { 'h', 'e', 'l', 'l', 'o' }; foreach (var x in one.Zip(two, (a,b) => new {A = a, B =b })) Console.WriteLine("{0} => '{1}'", xA, xB); 

结果是:

1 =>’h’
2 =>’e’
3 =>’l’
4 =>’l’
5 =>’o’

这里还有3个:

使列表大小相同,然后只需简单选择。

 (a.Count < b.Count ? a : b).AddRange(new double[Math.Abs(a.Count - b.Count)]); var c = a.Select((n, i) => n + b[i]); 

不要使它们具有相同的大小,但要经过最长时间并检查最短的范围结束(存储shortList.Count以便轻松获得增益):

 var longList = a.Count > b.Count ? a : b; var shortList = longList == a ? b : a; var c = longList.Select((n, i) => n + (shortList.Count > i ? shortList[i] : 0)); 

Take你所能,然后SkipUnion其余部分:

 var c = a.Take(Math.Min(a.Count, b.Count)) .Select((n, i) => n + b[i]) .Union(a.Skip(Math.Min(a.Count, b.Count)); 

作为Marc和Damian的答案的组合,您可以使用此代码,这是更多的生产准备:

 public static class EnumerableExtensions { public static IEnumerable Merge(this IEnumerable first, IEnumerable second, Func operation) { return Merge(first, second, operation); } public static IEnumerable Merge(this IEnumerable first, IEnumerable second, Func operation) { return Merge(first, second, operation); } public static IEnumerable Merge(this IEnumerable first, IEnumerable second, Func operation) { if (first == null) throw new ArgumentNullException(nameof(first)); if (second == null) throw new ArgumentNullException(nameof(second)); using (var iter1 = first.GetEnumerator()) using (var iter2 = second.GetEnumerator()) { while (iter1.MoveNext()) { yield return iter2.MoveNext() ? operation(iter1.Current, iter2.Current) : operation(iter1.Current, default); } while (iter2.MoveNext()) { yield return operation(default, iter2.Current); } } } } 

我使用循环实现:

 List shorter, longer; if (a.Count > b.Count) { shorter = b; longer = a } else { shorter = a; longer = b; } List result = new List(longer); for (int i = 0; i < shorter.Count; ++i) { result[i] += shorter[i]; }