【问题标题】:lambda expression with 2 parameters and mulitple result outputs具有 2 个参数和多个结果输出的 lambda 表达式
【发布时间】:2016-07-16 15:39:01
【问题描述】:

我正在尝试找出是否可以在 lambda 表达式函数中使用两个输入参数来获得可以放入数组中的多个结果,而不是像下面这样使用 for 循环。

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);

输出 2,1,1,1,3,4,2,11,17

类似这样的:

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

【问题讨论】:

    标签: c# methods lambda extension-methods


    【解决方案1】:

    您可以使用Zip 将数组与自身对齐,并移动一个索引:

    results = numbs.Zip(numbs.Skip(1), (n1, n2) => n2 - n1)
                   .ToArray();
    

    【讨论】:

    • 我以前从未听说过 ZIP,因为我仍在自学如何使用 Lambda 表达式。 @D Stanley 无论如何,您会为 ZIP 方法创建某种类型的标签吗?像 ZIP-method 或 method-ZIP
    【解决方案2】:

    您可以创建自己的扩展方法(不确定“标签”是什么意思)。您还可以创建自己的迭代器。两者可以很好地协同工作。这是一种将窗口函数应用于一个序列的迭代器扩展方法。

    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.)
        }
    }
    

    您的情况是窗口大小为 2 和差分函数的特例。

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

    功能有点尴尬。这不那么重要,但设置更笨重。

    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))
    

    更进一步

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

    有点花哨

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

    另一个例子:滑动平均

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

    但是,请查看LINQ's Standard Query Operators

    Code 为您的LINQPad(强烈推荐)。

    【讨论】:

    • “标签”请求是针对堆栈溢出标签的,因为 ZIP 没有引用 lambda 方法。至于你的解决方案 alli 可以说是真的吗?为什么我希望将我的代码行扩展十倍?我一直在寻找单行 lambda 解决方案。谢谢,但不,谢谢。
    • 同意你的情况。不过,窗口化很有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多