1

我有以下实体框架类定义:

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;
}

只是想知道是否有更快/更好的方法来做到这一点。

4

3 回答 3

3

您可以创建仅在满足某些条件时才返回项目的扩展方法。此条件(谓词)将接受两个参数 - 前一项和当前项,它应该比较它们:

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);
于 2013-06-25T12:13:58.947 回答
0

不知道这是否更好:)无论如何:

  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)。同样 for 循环可能更有效(但您要求使用 LINQ)。

于 2013-06-25T12:32:22.050 回答
0

再次阅读您的数据集后进行编辑。

我看到分组不起作用。理想情况下,由于网络 io 等,您希望在 db 服务器上而不是客户端上使用此逻辑。

您可以将其编写为 proc 或动态 sql。动态 sql 在短期内可能会更容易。

简单的方法,选择它变成一个游标。循环进入临时表变量并返回结果集。

如果您的数据集非常小,那么请坚持使用您拥有的易于阅读的 linq 循环。除非您也需要,否则不要增加更多复杂性。即不要进行微优化。

于 2013-06-25T12:12:16.890 回答