列表<>;迭代性能
本文关键字:迭代 性能 gt lt 列表 | 更新日期: 2023-09-27 18:26:31
嗨,我有一个关于在值列表中迭代的效率的问题。
我想知道的是,你必须查看一个值列表,从中提取出与当前搜索条件匹配的值,一旦找到匹配项,删除它是否有意义,从而在下一次迭代中搜索一个较小的值列表。或者这没什么区别。这是我的密码。
foreach (Project prj in projectList)
{
string prjCode = prj.Code;
var match = usersProjects.FirstOrDefault(x => x.Code == prjCode);
if (match != null)
{
usersProjects.Remove(match);
//More logic here
}
}
基本上,我正在从所有项目的列表中搜索与用户相对应的项目代码。假设有50个项目,用户可以访问其中的20个。删除找到的项目每个循环是否会减少整个项目的数量,从而提高迭代的效率?谢谢
我不建议更改列表——它本身很慢,顺序为O(n)。
使用准备好的查找来执行您想要的操作,而不是FirstOrDefault()
var projectLookup = usersProjects.ToLookup((x) => x.Code);
foreach (Project prj in projectList)
{
string prjCode = prj.Code;
var match = projectLookup[prjCode].FirstOrDefault()
if (match != null)
{
//More logic here
}
}
请注意,ToLookup()
非常昂贵,因此如果可能,您希望保留查找—请考虑仅在userProjects
更改时重新创建它。之后,实际使用查找来检索匹配只需要恒定的时间。
我建议对此使用组联接:
var matches =
from prj in projectList
join x in usersProjects on prj.Code equals x.Code into xs
where xs.Any()
select xs.First();
实际上,一个稍微好一点的查询是:
var matches =
from prj in projectList
join x in usersProjects on prj.Code equals x.Code into xs
from x1 in xs.Take(1)
select x1;
如果你需要从usersProjects
列表中删除它们,你需要这样做:
foreach (var match in matches)
{
usersProjects.Remove(match);
}
但是,如果你只想知道usersProjects
中还有什么如果你删除了匹配项,那么你可以这样做:
var remainingUsersProjects = usersProjects.Except(matches);
最后,您唯一需要做的就是时间所有选项,看看什么更快。
但我认为,除非你的清单很大,否则这真的无关紧要。否则,我会使用最简单易懂的代码,这样您就可以在未来维护您的项目。
您可以使用简单的Where()
方法来获取所有用户项目,而不是循环和多个FirstOrDefault()
调用:
userProjects = userProjects.Where(up => projectList.All(p => up.Code != p.Code))