C# 使用Lambda、Linq和实体框架选择值的更改
我有以下实体框架类定义:C# 使用Lambda、Linq和实体框架选择值的更改,c#,linq,lambda,C#,Linq,Lambda,我有以下实体框架类定义: 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 因此,结果将是:
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;
}
var timeValueQuery=\u context.TimeValues.Where(…);
List timeChanges=新列表();
TimeValue lastValue=null;
foreach(timeValueQuery中的var tvq)
{
if(lastValue==null | | tvq.Value!=lastValue.Value)
{
时间变化。添加(tvq);
}
lastValue=tvq;
}
只是想知道是否有更快捷/更好的方法。再次阅读数据集后编辑 我看分组是行不通的。理想情况下,您希望在db服务器上使用此逻辑,而不是由于网络io等原因而在客户端 您可以将其作为过程或动态sql编写。动态sql在短期内可能更容易实现 简单方法,将其选择到光标中。循环到临时表变量中并返回结果集
如果您的数据集非常小,那么请使用现有的易于阅读的linq循环。除非你需要,否则不要增加复杂性。i、 e.不要进行微优化。您可以创建扩展方法,该方法仅在满足某些条件时才会返回项目。此条件(谓词)将接受两个参数—previous和current item,它应该比较这两个参数:
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;
}
}
不知道这是否更好:)无论如何:
IQueryable值=…;//在这里初始化
var query=从v输入值
其中(从v2开始,以值为单位)
orderby v2.StartDate
其中v2.StartDate>v.StartDate
选择v2.Value).FirstOrDefault()!=v、 价值观
选择v;
如果可能为零值,请将FirstOrDefault()更改为FirstOrDefault(不可能的值)。同样,对于cycle,它可能更有效(但您要求的是LINQ)。这不起作用-如果它两次更改为相同的值,它将只给您最后一个值。@Andez感谢:)顺便说一句,我还要添加检查源是否为null,以避免NullReferenceExceptionSlever。只需确保数据是有序的。
var timeChanges = _context.TimeValues.TakeIf((x, y) => x.Value != y.Value);
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;