C# 将foreach转换为Linq
当前代码: 对于C# 将foreach转换为Linq,c#,linq,C#,Linq,当前代码: 对于MapEntryTable中的每个元素,检查属性IsDisplaydColumn和IsReturnColumn,如果它们为true,则将元素添加到另一组列表中,其运行时间将为O(n),许多元素的两个属性都为false,因此不会添加到循环中的任何列表中 foreach (var mapEntry in MapEntryTable) { if (mapEntry.IsDisplayedColumn) Type1.DisplayColumnId.Add(mapEn
MapEntryTable
中的每个元素,检查属性IsDisplaydColumn
和IsReturnColumn
,如果它们为true,则将元素添加到另一组列表中,其运行时间将为O(n)
,许多元素的两个属性都为false,因此不会添加到循环中的任何列表中
foreach (var mapEntry in MapEntryTable)
{
if (mapEntry.IsDisplayedColumn)
Type1.DisplayColumnId.Add(mapEntry.OutputColumnId);
if (mapEntry.IsReturnColumn)
Type1.ReturnColumnId.Add(mapEntry.OutputColumnId);
}
以下是执行相同操作的Linq版本:
MapEntryTable.Where(x => x.IsDisplayedColumn == true).ToList().ForEach(mapEntry => Type1.DisplayColumnId.Add(mapEntry.OutputColumnId));
MapEntryTable.Where(x => x.IsReturnColumn == true).ToList().ForEach(mapEntry => Type1.ReturnColumnId.Add(mapEntry.OutputColumnId));
我正在学习将所有这些foreach代码转换为linq,但我的问题是:
- 在这种情况下,Linq转换有什么优势还是劣势
- 是否有更好的方法使用Linq实现同样的功能
Type1
是一种自定义类型,具有一组List
结构、DisplayColumnId
和ReturnColumnId
我想说,使用foreach
循环时,请坚持原来的方式,因为您只在列表中重复了1次
此外,您的linq应该更像这样:
list1.DisplayColumnId.AddRange(MapEntryTable.Where(x => x.IsDisplayedColumn).Select(mapEntry => mapEntry.OutputColumnId));
list2.ReturnColumnId.AddRange(MapEntryTable.Where(x => x.IsReturnColumn).Select(mapEntry => mapEntry.OutputColumnId));
foreach与Linq-foreach的性能几乎完全相同,相差不到纳秒。假设在测试时,两个版本的循环中都有相同的内部逻辑 然而,作为一个for循环,它的表现大大优于这两种方法。for(int i;i
List<Thing> things = .....;
var oldThings = things.Where(p.DateTime.Year < DateTime.Now.Year);
即使我能像你一样写那本书
foreach(var node in thingNodes.Where(p => p.NodeType == "Thing" && !node.Ignore) {
thing.Add(node);
}
我想不出有什么真正的理由这么做..>
things.ForEach(thing => {
//do something
//can't break
//can't continue
return; //<- continue
});
things.ForEach(thing=>{
//做点什么
//不能打破
//无法继续
return;//在C#中,要在一次调用中实现您想要的功能,您必须编写自己的分区方法。如果您愿意使用F#,您可以使用List。分区ForEach
不是LINQ方法。它是List
的方法。它不仅不是LINQ的一部分,而且与Eric Lippet写的,当时他是C#编译器团队的原则开发人员
您的“LINQ”方法还包括:
- 完全不必要地复制要添加到列表中的所有项,这既浪费时间和内存,也与LINQ在执行查询时延迟执行的目标相冲突
- 实际上不是一个查询,但
Where
运算符除外。您操作的是查询中的项,而不是执行查询。LINQ是一个查询工具,而不是用于操作数据集的工具
- 您正在迭代源序列两次。这可能是问题,也可能不是问题,这取决于源序列的实际情况以及迭代的成本
一个尽可能多地使用LINQ的解决方案就是这样使用它:
foreach (var mapEntry in MapEntryTable.Where(entry => mapEntry.IsDisplayedColumn))
list1.DisplayColumnId.Add(mapEntry.OutputColumnId);
foreach (var mapEntry in MapEntryTable.Where(entry => mapEntry.IsReturnColumn))
list2.ReturnColumnId.Add(mapEntry.OutputColumnId);
您的LINQ不太正确,因为您正在将Where
的结果转换为列表,然后使用ForEach
对这些结果进行伪迭代以添加到另一个列表。使用ToList
或AddRange
将序列转换或添加到列表
例如,覆盖列表1
(如果它实际上是一个列表
):
或附加:
list1.AddRange(MapEntryTable.Where(x => x.IsDisplayedColumn == true)
.Select(mapEntry => mapEntry.OutputColumnId));
如果要稍微缩短代码,请去掉“==true”比较。x=>x.IsDisplayedColumn将返回true如果IsDisplayedColumn为true,则无需将其与实际值进行比较。您可能还调用了ToList()不必要的。@Andrew B第一部分是正确的,但第二部分是强制性的,Foreach是一个列表扩展方法,而不是IEnumerablew什么类型是list1和list2?我从未见过具有DisplayColumnId属性的列表……我肯定在这里遗漏了什么。无论如何,如果没有足够的信息来回答:您可能不需要ToList()。Foreach()
当您可以使用sequence.ToList()或list.AddRange(sequence)将序列分配或附加到列表中时
@MrinalKamboj那么你的名字都很容易让人误解。当变量不是列表时,你不应该有名为list1
和list2
的变量,而且名字DisplayColumnId
听起来根本不像是一个集合,它的名字意味着它是一个单数标识符。你为什么需要foreach?你可以o类似于Andrew建议的内容:list1.DisplayColumnId=MapEntryTable.Where(x=>x.isDisplaydColumn)。选择(mapEntry=>mapEntry.OutputColumnId);
list2.ReturnColumnId=MapEntryTable.Where(x=>x.IsReturnColumn)。选择(mapEntry=>mapEntry.OutputColumnId)
@Carlos假设list2.ReturnColumnId
的类型是IEnumerable
,并且那里的所有内容都应该替换为该内容。如果不是变量的类型,并且/或者该集合中的某些项也应该保留在那里,那么这将不起作用。啊,好的,这是有意义的。干杯!:)@非常感谢您的详细说明,我将坚持使用foreach,但是linq中的Where扩展方法会快速搜索元素,或者通过完整列表进行枚举,因此不会产生任何过滤的主要好处,因此我的
for (int i = 0; i < things.Count; ++i) {
var thing = things[i];
//do something
}
foreach (var mapEntry in MapEntryTable.Where(entry => mapEntry.IsDisplayedColumn))
list1.DisplayColumnId.Add(mapEntry.OutputColumnId);
foreach (var mapEntry in MapEntryTable.Where(entry => mapEntry.IsReturnColumn))
list2.ReturnColumnId.Add(mapEntry.OutputColumnId);
list1 = MapEntryTable.Where(x => x.IsDisplayedColumn == true)
.Select(mapEntry => mapEntry.OutputColumnId).ToList();
list1.AddRange(MapEntryTable.Where(x => x.IsDisplayedColumn == true)
.Select(mapEntry => mapEntry.OutputColumnId));