4

what is the best LINQ approach for with no performance loss? how could we do the same thing using LINQ iterating the list only once?

class Employee  
{  
    string name ...;  
    string age .....;  
    int empType ...;  
    int income ...;  
}  

List<Employee> myList ...;  
List<Employee> toList...;  
int totalIncomeOfToList = 0;  

foreach(Employee emp in myList)  
{  
    if(emp.empType == 1)  
    {  
        toList.Add(emp);  
        totalIncomeOfToList += emp.income;  
    }  
}  
2
  • get the trial period of resharper Commented Oct 22, 2013 at 14:43
  • Thank You for the solution guys. Happy to see quick responses for my first post. Commented Oct 22, 2013 at 15:47

3 Answers 3

13

(I'm assuming you want the filtered list as well - the other answers given so far only end up with the sum, not the list as well. They're absolutely fine if you don't need the list, but they're not equivalent to your original code.)

Well you can iterate over the original list just once - and then iterate over the filtered list afterwards:

var toList = myList.Where(e => e.empType == 1).ToList();
var totalIncomeOfToList = toList.Sum(e => e.income);

Admittedly this could be a bit less efficient in terms of blowing through the processor cache twice, but I'd be surprised if it were significant. If you can prove that it is significant, you can always go back to the "manual" version.

You could write a projection with a side-effect in it, to do it all in one pass, but that's so ugly that I won't even include it in the answer unless I'm really pressed to do so.

Sign up to request clarification or add additional context in comments.

4 Comments

+1 for being the only answer that populates the toList. I think that was the real problem why the question was asked.
Thanks Jon. You are right. I want the filtered list as well as the sum. Your solution is exactly what I had in my mind. However, I wanted to know if there is a solution that would match the same performance.
@user2907465: The performance difference is likely to be insignificant. I would use this and then find out whether or not this is actually a performance hit.
@user2907465 LINQ is never faster than the traditional loop with correct data structure, It can save you memory but always a little slower than traditional loop with some already-in-memory data, at least that's what I've experienced.
1

I know LINQ should not have side-effects, but for what it's worth ...

int totalIncomeOfToList = 0;  
List<Employee> toList = myList
    .Where(emp => emp.empType == 1)
    .Select(emp => { totalIncomeOfToList += emp.income; return emp; })
    .ToList();

2 Comments

Thanks Tim. Is this same as Jon's solution under the hood?
@Nith: I assume that it's what Jon mentioned in his last sentence("but that's so ugly that...") ;-)
1

Try this for getting the total income

var totalIncomeOfToList = myList.Where(e => e.empType == 1).Sum(e => e.income);

If you also want the list of filtered employees then:

var toList = myList.Where(e => e.empType == 1).ToList();
var totalIncomeOfToList = toList.Sum(e => e.income);

The performance will be slightly better with a foreach, but this way the code will be much clear and precise.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.