views:

133

answers:

2

Given two IEnumberables of different types, what is the best practice (considering readability and maintainability) for iterating over both lists to perform an action on all possible combinations?

My initial solution was to use nested foreach loops, iterating over the first IEnumerable, and then within that loop, iterating over the second IEnumerable and passing the value from the outer and the current loop into the target method. Eg.:

enum ParamOne
{
    First, 
    Second,
    Etc
}

List<int> paramTwo = new List<int>() { 1, 2, 3 };

void LoopExample()
{
    foreach (ParamOne alpha in Enum.GetValues(typeof(ParamOne)))
    {
        foreach (int beta in paramTwo)
        {
            DoSomething(alpha, beta);
        }
    }
 }

I tried to restructure it with LINQ, but ended up with something that had no obvious advantages and seemed less intuitive. A search here shows lots of questions about nesting foreachs to iterate over child properties, but I couldn't find anything about iterating over two distinct lists.

+1  A: 

I don't see anything particularly wrong with your solution. That being said, the simplest LINQ procedure would seem to be:

foreach(var entry in enumerable1.SelectMany(
            e => enumerable2.Select(e2 => new { First = e, Second = e2 })))
{
    DoSomething(entry.First, entry.Second);
}

Given that it's a little...obtuse...I would recommend sticking with the two foreach operations. That's less expensive than all of the shenanigans that the C# compiler is going to go through in order to make that expression work (since we're dealing both with closures and anonymous types).

Adam Robinson
That confirms my conclusion about it - the LINQ procedure I came up with was essentially the same as yours, and I agree that it seems much more obtuse than nesting the `foreach` loops.
jball
If on the other hand you need to filter out some stuff and can get LINQ to it, it might be a win.
BCS
@BCS: Obviously I can't argue with that statement, but I think it's better to go with the scenario presented in the question. Otherwise there's really no limit to the hypothetical situations that we can come up with to fit various solutions. In other words, I'd rather come up with a solution to fit the scenario, rather than a scenario to fit the solution ;)
Adam Robinson
I follow the school of, once you answer the original authors question, make the answer more useful to other people who might find it.
BCS
+1  A: 

As long as there is no overlap in the combinations, I don't see a more computationally efficient way of computing a function on the cartesian product of two sets. However, if either of the lists have duplicate elements, or the order of arguments to DoSomething doesn't matter and there is overlap within the lists, you will product redundant calls to DoSomething. You might save computational time by memoizing DoSomething.

frankc