# Iterate over two collections of equal length

What's the best way to iterate over two collections of equal length?

Currently I'm using this:

for(var index = 0; index < collection1.Count(); index++)
{
var item1 = collection1[index];
var item2 = collection2[index];
Console.WriteLine(item1.ToString() + ", "+ item2.ToString());
}


But I'd love to be able to use a foreach instead, e.g.

foreach(item1, item2 in collection1, collection2)
{
Console.WriteLine(item1.ToString() + ", " + item2.ToString();
}


Now, this would be sort of possible if I zipped my two collections into a dictionary, but is that the best way to go? Would that be a sufficient gain of readability while sacrificing the performance needed to build the dictionary?

Similarly, I'm not sure if a dictionary is idealistically correct here, as there may not necessarily be a link between the two collections (other than their order in the list), merely a guarantee that they both have the same length.

-

You can use LINQ's Zip method. As usual, it's a bit slower than manually written code, but unless this is in a hot spot it rarely matters. The cost of Console.WriteLine vastly exceeds the cost of LINQ.

foreach(var pair in collection1.Zip(collection2, Tuple.Create))
{
Console.WriteLine("{0}, {1}", pair.Item1, pair.Item2);
}

-
You could use collection1.Zip(collection2, Tuple.Create), right? –  codesparkle May 1 '14 at 14:55
@codesparkle Yes, that's better. Thanks for the suggestion. –  CodesInChaos May 1 '14 at 14:58
Swapped solution to here, as result was both readable and concise. Could an anonymous type be used here to make it clearer what one was working with inside the foreach body than simply using ".Item1" and ".Item2"? –  Nick Udell May 1 '14 at 22:19
Just had time to test it, you can swap Tuple.Create with (s,s2)=> new {type1=s,type2=s2} and reference it with pair.type1 and pair.type2 and this lets you use more sensible names later on. –  Nick Udell May 1 '14 at 23:57

The first one will always be more readable. If you want to start building collections that contain your previous collections, you'll add another layer of abstraction to your code for no reason: this will hurt readability a lot.

One of the limitations of the foreach loop is that it can only iterate one collection at a time. Working around this might seem interesting but I doubt there will be any solution that's more readable.

-

Another alternative:

using (var enumerator1 = collection1.GetEnumerator())
using (var enumerator2 = collection2.GetEnumerator()) {
while(enumerator1.MoveNext() && enumerator2.MoveNext()) {
Console.WriteLine(enumerator1.Current.ToString() + ", " + enumerator1.Current.ToString());
}
}

-
I think this is worse than the original code. I would use something like this only if I couldn't use indexers or Zip. –  svick May 1 '14 at 14:49

What's the best way to iterate over two collections of equal length?

Don't. This is often (but not always) an indication that the two collections should instead be one, of some compound type.

For example, if the collections represent 2D points, with the first one containing X coordinates and the second one Y coordinates, you should instead create a new Point type and have a collection of those.

-
Sometimes you have to iterate over two collections of equal length when working with an existing library that you either cannot modify the source of or do not have the time to refactor. Creating a compound collection from those for your own code could work, but might be overkill if you aren't holding on to the data for very long. I do like the zipping technique people have mentioned, but that's likely due to my background in Python, where zip is a built-in function. –  JAB May 1 '14 at 15:27
@JAB I agree, zipping is a reasonable solution to this when a compound collection doesn't make sense. –  svick May 1 '14 at 15:37