var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> { 1, 2, 3 };
What is the most elegant way to iterate through both yielding a set of results "a1", "b2", "c3"?
var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> { 1, 2, 3 };
What is the most elegant way to iterate through both yielding a set of results "a1", "b2", "c3"?
This is known as "zipping" or "zip joining" two sequences. Eric Lippert describes this very algorithm and provides an implementation.
The mighty Bart de Smet talks about zip functions here:
His most elegant solution takes advantage of an overload of select that takes a 2 parameter Func delegate as its parameter.
a.Select((t,i)=>new{t,i});
In this example, i simply represents the index of the item being processed. So you can create 2 new enumerables of these anonymous objects and join them on i.
Performance-wise, I'd go with a more obvious yielding loop.
To supplement the great posts by Eric and Bart, here's an implementation using System.Linq 3.5 operators:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector)
{
return from aa in a.Select((x, i) => new { x, i })
join bb in b.Select((y, j) => new { y, j })
on aa.i equals bb.j
select resultSelector(aa.x, bb.y);
}
You can create an iterator block to handle this elegantly:
public static class Ext
{
public static IEnumerable<string> ConcatEach(this IEnumerable a,
IEnumerable b)
{
var aItor = a.GetEnumerator();
var bItor = b.GetEnumerator();
while (aItor.MoveNext() && bItor.MoveNext())
yield return aItor.Current.ToString() + bItor.Current;
}
}
Call it elegantly =) as:
var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> {1, 2, 3};
foreach(var joined in a.ConcatEach(b))
{
Console.WriteLine(joined);
}