在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查询中挤压这一切,包括加入索引,但那些会非常慢而且毫无意义。
1
和2
和3
什么? 如果您正在寻找不同的价值观:
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
你所能,然后Skip
并Union
其余部分:
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]; }
- System.Threading.Timer vs System.Threading.Thread.Sleep resolution – .NET Timer不使用系统时钟分辨率
- 是否有一种文化安全的方法来获取带有前导零的ToShortDateString()和ToShortTimeString()?
- 将BitmapFrame用于元数据而不锁定文件
- 使用C#中的Exchange Web服务托管API检索错误的邮箱项目
- 如何在XmlDocument()上从URL加载XML
- 如何使用文件系统驱动程序隐藏C#中的目录?
- 复选框控制按钮启用属性 – ASP.NET
- 下载-ItextSharp时生成空白pdf
- 如果Entity Framework / DbContext是DAL / Repository,它在哪里适合3层架构?