简体   繁体   中英

Accessing a List multiple times in same code block - Any better approach?

I need to set the values of multiple labels from a single list based on different conditions. Here is my code:

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();
}

I am afraid that this approach may affect the performance as everytime you need a value you traverse the list. Any suggestion for the better approach will be highly appreciated.

Use a GroupBy (preferably at the db IQueryable level), then for extra flavor you can to ToDictionary to make the look up more efficient

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];
...

The assumption is the StatusID maps one to one with ProjectStatus

Note the additional Select , is superfluous however is added for in-case you just wanted a list


Additional Resources

Enumerable.GroupBy Method

Groups the elements of a sequence.

Enumerable.Select Method

Projects each element of a sequence into a new form.

Enumerable.ToDictionary Method

Creates a Dictionary from an IEnumerable.

You can do something like this, only looping through the list once (here I only show 4 counts. You can easily add the rest yourself):

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();

But only do this if this particular code is actually causing a performance problem. Don't optimise prematurely.

You could easily use ToLookup like this:

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

Replace the x in the lookup[x] part with the appropriate enums.

Lookup would be a good solution to have.

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  ......

You can read more on Lookup here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM