在同一代码块中多次访问列表-更好的方法吗?

时间:2019-01-22 06:44:11

标签: c# asp.net performance linq

我需要根据不同条件从单个列表中设置多个标签的值。这是我的代码:

List<RFPModel> lst = RFPModel.GetAll();  //ALL
if(lst.Count>0)
{
    lblActive.InnerText = lst.Count(a => a.StatusID == (int)ProjectStatus.Project_Active).ToString();
    lblCompleted.InnerText = lst.Count(a => a.StatusID == (int)ProjectStatus.Project_Completed).ToString();
    lblProposal.InnerText = lst.Count(a => a.StatusID == (int)ProjectStatus.Proposal_UnderProcess).ToString();
    lblProposalsRej.InnerText = lst.Count(a => a.StatusID == (int)ProjectStatus.Proposal_Rejected).ToString();
    lblRFPRec.InnerText= lst.Count(a => a.StatusID == (int)ProjectStatus.RFP_Submitted).ToString();
    lblRFPRef.InnerText= lst.Count(a => a.StatusID == (int)ProjectStatus.RFP_Rejected).ToString();
    lblRFPApp.InnerText = lst.Count(a => a.StatusID == (int)ProjectStatus.RFP_Approved).ToString();
}

恐怕这种方法可能会影响性能,因为每次遍历列表时都需要一个值。任何对更好方法的建议将不胜感激。

4 个答案:

答案 0 :(得分:6)

使用GroupBy(最好是在数据库IQueryable级别),然后可以使用ToDictionary以获得更多的风味

var dict = lst.GroupBy(x => x.StatusID)
             .Select(x => new { x.Key, count = x.Count() })
             .ToDictionary(x => (ProjectStatus)x.Key, x => x.count.ToString());

lblActive.InnerText  = dict[ProjectStatus.Project_Active];
lblCompleted.InnerText  = dict[ProjectStatus.Project_Completed];
...

假设StatusIDProjectStatus一对一映射

请注意,多余的Select是多余的,但是如果您只是想要一个列表,则会添加


其他资源

Enumerable.GroupBy Method

  

对序列的元素进行分组。

Enumerable.Select Method

  

将序列的每个元素投影为新形式。

Enumerable.ToDictionary Method

  

从IEnumerable创建字典。

答案 1 :(得分:2)

您可以执行以下操作,仅在列表中循环一次(这里我仅显示4个计数。您可以自己轻松添加其余计数):

int activeCount = 0;
int completedCount = 0;
int proposalCount = 0;
int proposalRejCount = 0;
foreach (var item in lst) {
    if (item.StatusID == (int)ProjectStatus.Project_Active) 
        activeCount++;
    else if (item.StatusID == (int)ProjectStatus.Project_Completed) 
        completedCount++;
    else if (item.StatusID == (int)ProjectStatus.Project_UnderProcess) 
        proposalCount++;
    else if (item.StatusID == (int)ProjectStatus.Project_Proposal_Rejected) 
        proposalRejCount++;
}

lblActive.InnerText = activeCount.ToString();
lblCompleted.InnerText = completedCount.ToString();
lblProposal.InnerText = proposalCount.ToString();
lblProposalRej.InnerText = proposalRejCount.ToString();

但是仅当此特定代码实际上导致性能问题时才这样做。不要过早优化。

答案 2 :(得分:1)

您可以像这样轻松使用ToLookup

List<RFPModel> lst = new List<RFPModel>();
lst.Add(new RFPModel { StatusID = 1 });
lst.Add(new RFPModel { StatusID = 1 });
lst.Add(new RFPModel { StatusID = 1 });
lst.Add(new RFPModel { StatusID = 2 });
lst.Add(new RFPModel { StatusID = 2 });
lst.Add(new RFPModel { StatusID = 3 });
lst.Add(new RFPModel { StatusID = 4 });
lst.Add(new RFPModel { StatusID = 4 });
lst.Add(new RFPModel { StatusID = 4 });
lst.Add(new RFPModel { StatusID = 4 });
lst.Add(new RFPModel { StatusID = 5 });

var lookup = lst.ToLookup(p => p.StatusID);

var status1Count = lookup[1].Count(); // 3
var status2Count = lookup[2].Count(); // 2
var status3Count = lookup[3].Count(); // 1
var status4Count = lookup[4].Count(); // 4
var status5Count = lookup[5].Count(); // 1

用适当的枚举替换 lookup [x] 部分中的 x

答案 3 :(得分:1)

查找将是一个很好的解决方案。

List<RFPModel> lst = RFPModel.GetAll();  //ALL
var lookup = lst.ToLookup(x=>x.StatusID);
lblActive.InnerText = lookup[(int)ProjectStatus.Project_Active].Count();
lblCompleted.InnerText = lookup[(int)ProjectStatus.Project_Completed].Count();
and so on  ......

您可以阅读有关查询here

的更多信息