列表<>;迭代性能

本文关键字:迭代 性能 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))