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

查看:91
本文介绍了使用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的序列-例如,您可能想在"dummy"第一个元素前添加前缀. (或将方法更改为包括一种.)

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天全站免登陆