使用LINQ计算与上一项的差异 [英] Calculate difference from previous item with 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屋!