How can combine two enumerations with a custom fun

2019-07-20 06:25发布

问题:

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?

回答1:

You can use Enumerable.Zip.

e.g.

var c = a.Zip(b, (a, b) => SomeFunc(a, b));


回答2:

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


回答3:

You can use Enumerable.Zip. Given a function f(A, B), you would have

var c = a.Zip(b, (aItem, bItem) => f(aItem, bItem)); 


回答4:

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