Linq:根据条件计算两个条目之间的差异(前瞻)
Posted
技术标签:
【中文标题】Linq:根据条件计算两个条目之间的差异(前瞻)【英文标题】:Linq: Calculate difference between two entries based on condition (lookahead) 【发布时间】:2022-01-08 20:35:31 【问题描述】:数据库包含带有设备特定代码的错误日志条目。如果代码为非 0 则错误为活动,为 0 则为无效。一次只能激活一个错误,因此存在设备“出错”和“未出错”的时间范围;但是可以同时发布许多其他错误代码(这与设备错误状态无关,此处感兴趣)。
我想计算设备“出错”的次数。不幸的是,我们不能假设错误总是交替出现(101, 0, 200, 0, 302, 0)
,但可能更混乱(3, 101, 0, 20, 202, 10, 0, 0, 102, ...)
。在这里,每次的错误时间都是从第一个非零错误码开始计算到第一个0,所以第一个非零出现到第一个零出现之间的时间差,然后从第一个非零开始等等。
换句话说:
timeStamp code
100 101
200 0
300 500
350 501
400 0
--> Total Error Time = 200 ((200 - 100) + (400 - 300))
在循环中,这将是这样的任务:
totalErrorTime = 0;
previousError = errors.FirstOrDefault(x => x.code != 0);
errors.forEach(error =>
if (previousError.code == 0 && error.code != 0)
// Set first encountered non zero error code
previousError = error;
if (error.code == 0)
// Encountered 0 error code, calculate difference
totalErrorTime += error.timeStamp - previousError.timeStamp;
// Set previous error to this error for lookahead
previousError = error;
但我想知道如何在 Linq 中执行类似的操作。到目前为止,我在想这样的事情:
var skippedErrors = errors;
result = errors
.Zip(skippedErrors.Skip(1).SkipWhile(x => x.code != 0), (a, b) => new
errorTime = b.timeStamp - a.timeStamp
)
.Select(x => new ErrorTimeResult(x.Sum(y => y.errorTime))));
但是,我认为SkipWhile()
部分并不安全。
如何在 Linq 中进行这些“前瞻”?我认为Zip()
是正确的方法,但我怎样才能确保只计算每个“错误阶段”一次?谢谢。
【问题讨论】:
在数据库级别执行此操作不是更简单、更高效吗? 【参考方案1】:我认为您需要对值进行规范化,然后执行子查询,然后执行 group by 以获取数据,如下所示:
using System;
using System.Linq;
using Newtonsoft.Json;
public class Program
public static void Main()
var l = (new[]
new TimeStamp = 100, Code = 0 ,
new TimeStamp = 200, Code = 2 ,
new TimeStamp = 300, Code = 3 ,
new TimeStamp = 400, Code = 0 ,
new TimeStamp = 520, Code = 34 ,
new TimeStamp = 50, Code = 2 ,
new TimeStamp = 500, Code = 0
).ToList();
l = l.OrderBy(a => a.TimeStamp).ToList();
var err = l.OrderBy(a => a.TimeStamp).Select(a => new
code = a.Code == 0 ? 0 : 1,
a.TimeStamp,
last = l.FirstOrDefault(b => b.TimeStamp > a.TimeStamp)?.Code == 0 ? 0 : 1,
lastTimestamp = l.FirstOrDefault(b => b.TimeStamp > a.TimeStamp)?.TimeStamp
).GroupBy(a => new a.code, a.last,
a => new a.TimeStamp, a.lastTimestamp ,
(key, g) => new
key.code, key.last, timestamp = g.Max(b => b.TimeStamp),
lastTimestamp = g.Min(b => b.lastTimestamp)
).OrderBy(a => a.timestamp);
Console.Write(JsonConvert.SerializeObject(err,Formatting.Indented));
在这里测试:https://dotnetfiddle.net/
【讨论】:
感谢您的回答。我正在尝试理解它,并会在我实施后报告。以上是关于Linq:根据条件计算两个条目之间的差异(前瞻)的主要内容,如果未能解决你的问题,请参考以下文章