views:

90

answers:

2

I could convert them to lists and just use a regular for loop with indexes, but I'm wondering if there's a way to do it that keeps them as IEnumerables.

+5  A: 

I think you want the new Zip feature from .NET 4.0. Eric Lippert blogged about it recently and included a simple form of the implementation.

It's also in MoreLINQ, in Zip.cs, which allows for different options if the sequences aren't the same length. The "default" is to act like .NET 4.0, stopping when either sequence runs out of elements. Alternatives are to pad the shorter sequence or throw an exception.

Jon Skeet
Right, that was one of the things I really liked about Python for the week or so that I played with it was that with Zip being a built-in function there are very very few cases where a tradition for loop was needed and they emphasized that by making you have to do a mini-hack to get traditional for loop behavior. Glad to see that it'll be making it int C#4
Davy8
+5  A: 

By default there is no way but it's not difficult to add an extension method to make it a bit easier. I excluded some error checking to ensure they were both the same length for brevity.

public static void ForEachPair<T1,T2>(
  this IEnumerable<T1> source1, 
  IEnumerable<T2> source2,
  Action<T1,T2> del) {
  using ( var e1 = source1.GetEnumerator() )
  using ( var e2 = source2.GetEnumerator() ) {
    while ( e1.MoveNext() && e2.MoveNext() ) {
      del(e1.Current, e2.Current);
    }
  }
}

Now you can do the following

var list = GetSomeList();
var otherList = GetSomeOtherList();
list.ForEachPair(otherList, (x,y) => 
{
   // Loop code here
});
JaredPar
IMO, you got it right, Zip is something different.
leppie
@Jared: I think you meant your "if" to be a "while". @leppie: In what way is this different to "Zip" other than providing the result as an IEnumerable (which you can then act on with a foreach) instead of passing a delegate to execute?
Jon Skeet
Useful little function there. Small suggestion: there's no need to nest the using statements.
Noldorin
Jon seems to be right about the while loop as well. Hope you don't mind the edit.
Noldorin
@Noldorin, They either must be nested or a try/finally must be used. How would you accomplish this without nested them? And yes, @Jon was right about the while (thanks for the update)
JaredPar
Think I'm going to accept this for reminding me how foreach works under the hood. I've never had to work with the enumerators myself before, because the only times I've needed to enumerate a collection a foreach loop does it for me nicely.
Davy8
You don't need to "nest" them if the declared types are the same. "using(Foo foo1 = GetFoo(), foo2 = GetAnotherFoo()) statement;" is a syntactic sugar for "using(Foo foo1 = GetFoo()) using (Foo foo2 = GetAnotherFoo) statement;" (But you cannot use "var" with the multple declaration form.)
Eric Lippert
@eric-lippert ah. Didn't realize that was supported syntax C#. Thanks!
JaredPar