[英]Selecting changes in values with Lambda, Linq, Entity Framework
我有以下Entity Framework类定义:
class TimeValue
{
DateTime StartDate;
double Value;
}
假设给出以下一系列值,我只想知道值何时更改:
2000-01-01 100
2000-01-15 100
2000-02-01 110
2000-02-15 120
2000-03-01 120
2000-03-15 50
2000-04-01 50
2000-04-15 50
2000-05-01 120
结果将是:
2000-01-01 100
2000-02-01 110
2000-02-15 120
2000-03-15 50
2000-05-01 120
我可以使用lambda / linq选择合适的值。 然后我使用以下代码迭代结果以添加到列表:
var timeValueQuery = _context.TimeValues.Where(...);
List<TimeValue> timeChanges = new List<TimeValue>();
TimeValue lastValue = null;
foreach (var tvq in timeValueQuery)
{
if (lastValue == null || tvq.Value != lastValue.Value)
{
timeChanges.Add(tvq);
}
lastValue = tvq;
}
只是想知道是否有更快/更好的方法来做到这一点。
您可以创建仅在满足某些条件时才返回项目的扩展方法。 这个条件(谓词)将接受两个参数 - 上一个和当前项,它应该比较:
public static IEnumerable<T> TakeIf<T>(this IEnumerable<T> source,
Func<T, T, bool> predicate)
{
var enumerator = source.GetEnumerator();
if (!enumerator.MoveNext())
yield break;
yield return enumerator.Current;
T previous = enumerator.Current;
while (enumerator.MoveNext())
{
T current = enumerator.Current;
if (predicate(previous, current))
yield return current;
previous = current;
}
}
传递谓词,检查先前和当前项目是否具有不同的值。 用法:
var timeChanges = _context.TimeValues.TakeIf((x, y) => x.Value != y.Value);
在再次读取数据集后编辑。
我看到分组不起作用。 理想情况下,由于网络io等原因,您希望在数据库服务器上使用此逻辑,而不是客户端。
您可以将其写为proc或动态sql。 动态sql在短期内可能更容易。
简单的方法,选择它进入游标。 循环到临时表变量并返回结果集。
如果您的数据集非常小,那么请坚持使用易读的linq循环。 除非您需要,否则不要增加复杂性。 即不要微观优化。
不知道这是不是更好:)反正:
IQueryable<TimeValue> values = ...; // initialize here
var query = from v in values
where (from v2 in values
orderby v2.StartDate
where v2.StartDate > v.StartDate
select v2.Value).FirstOrDefault() != v.Value
select v;
如果可以为零,则将FirstOrDefault()更改为FirstOrDefault(impossible_value)。 对于循环也可能更有效(但你要求LINQ)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.