问题描述:

I am trying to find out if it is possible having two input parameters in a lambda expression function to have multiple results that can be put into an array, instead of using a for loop like below.

int N = 10;

int[] numbs = new int[N] { 3, 5, 6, 7, 8, 11, 15, 17, 28, 55 };

int[] results = new int[N-1];

for (int i=0; i < N-1; i++)

results[i] = numbs[i+1] - numbs[i];

foreach (int i in results)

Console.WriteLine(i);

output 2,1,1,1,3,4,2,11,17

Something like this:

results = numbs.Select( (x,y) => y-x );

网友答案:

You could use Zip to line up the array with itself, shifted by one index:

results = numbs.Zip(numbs.Skip(1), (n1, n2) => n2 - n1)
               .ToArray();
网友答案:

You can create you own extension methods (not sure what you mean by "tag"). You can also create your own iterators. The two can work well together. Here is an iterator extension method for applying a windowing function to one sequence.

public static class SlidingWindowExtensions
{
    public static IEnumerable<T> Sliding<T>(this IEnumerable<T> source, Int32 windowSize, Func<IEnumerable<T>, T> function)
    {
        if (source == null) throw new ArgumentNullException(nameof(source));            
        if (windowSize <= 0) throw new ArgumentOutOfRangeException(nameof(windowSize), "Must be a positive integer");
        if (function== null) throw new ArgumentNullException(nameof(function));         

        var window = new Queue<T>(source.Take(windowSize - 1));
        foreach (var element in source.Skip(windowSize - 1))
        {
            window.Enqueue(element);
            var result = function(window);
            window.Dequeue();
            yield return result;
        }
        //Note: does not yield any result if window size is more than the length of the sequence. 
        //      (At least, that way function is guaranteed to get windowSize elements.)
    }
}

Yours would be a special case of a window size of 2 and a difference function.

numb.Sliding(2, w => w.Skip(1).First() - w.First())

The function is a bit awkward. This is less so but has a more clunky setup.

Func<IEnumerable<int>, int> first = w => w.First();
Func<IEnumerable<int>, int> second = w => w.Skip(1).First();

numbs.Sliding(2, w => second(w) - first(w))

A step further

Func<IEnumerable<int>, int> diff = w => second(w) - first(w);   
numbs.Sliding(2, diff)

A bit fancier

Func<IEnumerable<int>, IEnumerable<int>> slidingDifference = source => source.Sliding(2, diff);
slidingDifference(numbs)

Another example: sliding average

numbs.Sliding(2, w => (w.Sum() / 2))

But, do check out LINQ's Standard Query Operators.

Code for your LINQPad (highly recommended).

相关阅读:
Top