HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Iterate over two collections of equal length

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
equallengthiteratetwocollectionsover

Problem

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.

Solution

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 can replace Tuple.Create by ValueTuple.Create if you target .net 4.7 or you referenced the compatibility nuget package. This saves a heap allocation and is usually faster.

In C# 7 you could use named tuples, which enables meaningful property names. It's based on ValueTuple and thus avoid the heap allocation as well.

names.Zip(ages, (name, age) => (Name:name, Age:age))

Code Snippets

foreach(var pair in collection1.Zip(collection2, Tuple.Create))
{
    Console.WriteLine("{0}, {1}", pair.Item1, pair.Item2);
}
names.Zip(ages, (name, age) => (Name:name, Age:age))

Context

StackExchange Code Review Q#48661, answer score: 12

Revisions (0)

No revisions yet.