嗨,我对迭代值列表的效率有疑问。
我想知道你必须查看一个值列表,提取符合当前搜索条件的值,删除找到的匹配项是否有意义,从而产生较小的列表在下一次迭代中搜索的值。或者这没什么区别。这是我的代码。
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个。是否每次循环删除找到的项目都会减少整个项目的数量,从而使迭代更有效率?谢谢。
答案 0 :(得分:3)
我不建议更改列表 - 它本身很慢,命令为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
更改时重新创建查找。之后,实际使用查找来检索匹配只需要恒定的时间。
答案 1 :(得分:1)
我建议使用群组加入:
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);
在所有这一切结束时,您唯一需要做的就是时间所有选项,以便了解更快的内容。
但我认为除非你的名单很庞大,否则这无关紧要。否则,我会选择最简单的代码,以便将来维护您的项目。
答案 2 :(得分:0)
您可以使用简单的FirstOrDefault()
方法来获取所有用户项目,而不是循环和多个Where()
调用:
userProjects = userProjects.Where(up => projectList.All(p => up.Code != p.Code))