使用 LINQ 计算与前一项的差异 [英] Calculate difference from previous item with LINQ

查看:30
本文介绍了使用 LINQ 计算与前一项的差异的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 LINQ 为图表准备数据.

I'm trying to prepare data for a graph using LINQ.

我无法解决的问题是如何计算与之前的差异.

The problem that i cant solve is how to calculate the "difference to previous.

我期望的结果是

ID= 1,日期= 现在,DiffToPrev= 0;

ID= 1, Date= Now, DiffToPrev= 0;

ID= 1,日期= 现在+1,DiffToPrev= 3;

ID= 1, Date= Now+1, DiffToPrev= 3;

ID= 1,日期= 现在+2,DiffToPrev= 7;

ID= 1, Date= Now+2, DiffToPrev= 7;

ID= 1,日期= 现在+3,DiffToPrev= -6;

ID= 1, Date= Now+3, DiffToPrev= -6;

等等...

你能帮我创建一个这样的查询吗?

Can You help me create such a query ?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class MyObject
    {
        public int ID { get; set; }
        public DateTime Date { get; set; }
        public int Value { get; set; }
    }

    class Program
    {
        static void Main()
        {
               var list = new List<MyObject>
          {
            new MyObject {ID= 1,Date = DateTime.Now,Value = 5},
            new MyObject {ID= 1,Date = DateTime.Now.AddDays(1),Value = 8},
            new MyObject {ID= 1,Date = DateTime.Now.AddDays(2),Value = 15},
            new MyObject {ID= 1,Date = DateTime.Now.AddDays(3),Value = 9},
            new MyObject {ID= 1,Date = DateTime.Now.AddDays(4),Value = 12},
            new MyObject {ID= 1,Date = DateTime.Now.AddDays(5),Value = 25},
            new MyObject {ID= 2,Date = DateTime.Now,Value = 10},
            new MyObject {ID= 2,Date = DateTime.Now.AddDays(1),Value = 7},
            new MyObject {ID= 2,Date = DateTime.Now.AddDays(2),Value = 19},
            new MyObject {ID= 2,Date = DateTime.Now.AddDays(3),Value = 12},
            new MyObject {ID= 2,Date = DateTime.Now.AddDays(4),Value = 15},
            new MyObject {ID= 2,Date = DateTime.Now.AddDays(5),Value = 18}

        };

            Console.WriteLine(list);   

            Console.ReadLine();
        }
    }
}

推荐答案

一种选择(对于 LINQ to Objects)是创建您自己的 LINQ 运算符:

One option (for LINQ to Objects) would be to create your own LINQ operator:

// I don't like this name :(
public static IEnumerable<TResult> SelectWithPrevious<TSource, TResult>
    (this IEnumerable<TSource> source,
     Func<TSource, TSource, TResult> projection)
{
    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
             yield break;
        }
        TSource previous = iterator.Current;
        while (iterator.MoveNext())
        {
            yield return projection(previous, iterator.Current);
            previous = iterator.Current;
        }
    }
}

这使您能够仅使用源序列的一次传递来执行投影,这总是一个好处(想象一下在大型日志文件上运行它).

This enables you to perform your projection using only a single pass of the source sequence, which is always a bonus (imagine running it over a large log file).

请注意,它会将长度为 n 的序列投影到长度为 n-1 的序列中 - 例如,您可能想要添加虚拟"第一个元素.(或更改方法以包含一个.)

Note that it will project a sequence of length n into a sequence of length n-1 - you may want to prepend a "dummy" first element, for example. (Or change the method to include one.)

以下是您将如何使用它的示例:

Here's an example of how you'd use it:

var query = list.SelectWithPrevious((prev, cur) =>
     new { ID = cur.ID, Date = cur.Date, DateDiff = (cur.Date - prev.Date).Days) });

请注意,这将包括一个 ID 的最终结果和下一个 ID 的第一个结果……您可能希望首先按 ID 对序列进行分组.

Note that this will include the final result of one ID with the first result of the next ID... you may wish to group your sequence by ID first.

这篇关于使用 LINQ 计算与前一项的差异的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆