Given are two IEnumerable<A> a
and IEnumerable<B> b
. It is guaranteed that they are of the same length. I would like to create a new IEnumerable<C> c
in which each item c_i
is derived using a Func<A, B, C> f
by c_i := f (a_i, b_i)
.
The best I could come up with is manual simultaneous enumeration over both sources and yield-ing the current result, implemented as an extension method. Is there a short way to do it without custom code in .NET >= 4.0?
You can use Enumerable.Zip
.
e.g.
var c = a.Zip(b, (a, b) => SomeFunc(a, b));
Use Zip
method.
http://msdn.microsoft.com/en-us/library/dd267698.aspx
Applies a specified function to the corresponding elements of two
sequences, producing a sequence of the results.
int[] numbers = { 1, 2, 3, 4 };
string[] words = { "one", "two", "three" };
var numbersAndWords = numbers.Zip(words, (first, second) => first + " " + second);
foreach (var item in numbersAndWords)
Console.WriteLine(item);
// This code produces the following output:
// 1 one
// 2 two
// 3 three
You can use Enumerable.Zip. Given a function f(A, B)
, you would have
var c = a.Zip(b, (aItem, bItem) => f(aItem, bItem));
An alternative solution to the Zip extension method can be achieved using nested Select and SelectMany to flatten the result. The implementation should take only the elements with the same index in the list (not the cross product):
private int fun(int a, int b)
{
return a * b;
}
var l1 = new List<int> { 1, 2, 3 };
var l2 = new List<int> { 4, 5, 6 };
var r = l1.Select((e1, i1) => l2.Select ((e2, i2) => i1 == i2 ? fun(e1, e2) : 0))
.SelectMany (flat => flat)
.Where(re => re != 0)
.ToList();
The output in this case is:
4
10
18