tags:

views:

114

answers:

6

I have a huge IEnumerable(suppose the name is myItems), which way is more effective?

Solution 1: Filter it first then ForEach.

Array.ForEach(myItems.Where(FILTER-IT-HERE).ToArray(),MY-ACTION);

Solution 2: Do RETURN in MY-ACTION if the item is not up to the mustard.

Array.ForEach(myItems.ToArray(),MY-ACTION-WITH-FILTER);

Is one of them always better than another? Or any other good suggestions? Thanks in advance.

+2  A: 

Did you do any measurements? Since WE can't measure the run time of My-Action then only you can. Measure and decide.

Jared Peless
+2  A: 

Sometimes one has to create benchmark's because similar looking activities could produce radically different and unexpected results.

You do not say what your data source is so I'm going to assume it may be data on an SQL server in which case filtering at the server side will likely always be the best approach because you have minimalized the amount of data transfer. Memory access is always faster than data transfer from disk to memory so whenever you can transfer fewer records, you are likely to have better performance.

Regards,
Gerry (Lowry)

gerryLowry
A: 

I would say that this falls into the category of premature optimization. If, after establishing benchmarks, you find that the code is too slow, you can always try each approach and pick the result that works better for you.

Since we don't know how the IEnumerable<> is produced it's hard to say which approach will perform better. We also don't know how many items will remain after you apply your predicate - nor do we know whether the action or iteration steps are going to be the dominant factor in the execution of your code. The only way to know for sure is to try it both ways, profile the results, and pick the best.

Performance aside, I would choose the version that is most clear - which (for me) is to first filter and then apply the projection to the result.

LBushkin
+2  A: 

Well, both times, you're converting to an array, which might not be so efficient if the IEnumerable is very large (like you said). You could create a generic extension method for IEnumerable, like:

public static void ForEach<T>(this IEnumerable<T> current, Action<T> action) {
    foreach (var i in current) {
        action(i);
    }
}

and then you could do this:

IEnumerable<int> ints = new List<int>();
ints.Where(i => i == 5).ForEach(i => Console.WriteLine(i));
Pwninstein
A: 

If performance is a concern, it's unclear to me why you'd be bothering to construct an entire array in the first place. Why not just this?

foreach (var item in myItems.Where(FILTER-IT-HERE))
    MY-ACTION;

Or:

foreach (var item in myItems)
    MY-ACTION-WITH-FILTER;

I ask because, while the others are right that you can't really know without testing, I wouldn't expect there to be much difference between the above two options. I would expect there to be a difference, on the other hand, between creating/populating an array (seemingly for no reason) and not creating an array.

Dan Tao
+1  A: 

Everything else being equal, calling ToArray() first will impart a greater performance hit than when calling it last. Although, as has been stated by others before me,

  1. Why use ToArray() and Array.ForEach() at all?
  2. We don't know that everything else actually is equal since you do not reveal the implementation details of your filter and action.
Phong