代码优化以检查复选框列表的某些项目

时间:2013-07-25 12:45:50

标签: c# asp.net performance linq

请考虑以下代码段

列出orderList; //此列表已预先填充

foreach (System.Web.UI.WebControls.ListItem item in OrdersChoiceList.Items) // OrdersChoiceList is of type System.Web.UI.WebControls.CheckBoxList
{
     foreach (Order o in orderList)
     {
           if (item.id == o.id)
           {
               item.Selected = scopeComputer.SelectedBox;
               break;
           }
     }
}

列表中有数千个项目,因此这些循环非常耗时。我们如何才能优化它?

另外,我们如何使用LINQ做同样的事情。我尝试使用join操作,但无法根据“SelectedBox”设置“Selected”变量的值。现在我把select子句中的值硬编码为“true”,我们怎样才能通过&在select子句中使用SelectedBox值

                 var v = (from c in ComputersChoiceList.Items.Cast<ListItem>()
                                    join s in scopeComputers on c.Text equals s.CName
                                        select c).Select(x=>x.Selected = true);

1 个答案:

答案 0 :(得分:3)

我认为您需要消除嵌套迭代。如您所述,两个列表都有大量项目。如果它们都有5,000个项目,那么在最坏的情况下你会看到25,000,000次迭代。

没有必要为每个orderList不断重复ListItem次。而是创建一个ID查找,以便对每个ID进行快速O(1)查找。不确定涉及scopeComputer.SelectedBox会涉及哪些工作,但也可以在循环外解决。

bool selectedState = scopeComputer.SelectedBox;
HashSet<int> orderIDs = new HashSet<int>(orders.Select(o => o.id));

foreach (System.Web.UI.WebControls.ListItem item in OrdersChoiceList.Items)
{
    if (orderIDs.Contains(item.id))
        item.Selected = selectedState;
}

使用HashSet查找,您现在实际上只迭代了5,000次加上超快速查找。

编辑:据我所知,id上没有ListItem属性,但我假设您发布的代码是为了简洁起见,但很大程度上代表了整个过程。我将保留我的代码API /用法以匹配您的代码;我假设它可以翻译回你的具体实现。

编辑:根据您编辑过的问题,我认为您正在检索scopeComputer引用另一个查找/迭代。同样,您可以为此进行另一次查找:

HashSet<int> orderIDs = new HashSet<int>(orders.Select(o => o.id));
Dictionary<string, bool> scopeComputersSelectedState = 
    scopeComputers.ToDictionary(s => s.CName, s => s.Selected);

foreach (System.Web.UI.WebControls.ListItem item in OrdersChoiceList.Items)
{
    if (orderIDs.Contains(item.id))
        item.Selected = scopeComputersSelectedState[item.Text];
}

同样,不确定您的确切类型/用途。你可能也会用一个LINQ查询来压缩它,但我不认为(性能说话)你会看到很多改进。我也假设每个ScopeComputer条目都匹配ListItem.Text,否则在访问scopeComputersSelectedState[item.Text]时会出现异常。如果没有,那么你应该做一个简单的练习来改变它来执行TryGetValue查找。