c#linq过滤词典<datetime,int =“”>按预定义的最小时差

时间:2017-07-02 09:18:45

标签: c# linq dictionary

我需要过滤Dictionary<DateTime, int>的数据,以便只获取后续DateTime's之间的差异为1分钟或更长时间的元素。

例如,在字典中我可以拥有这样的数据对:

var pairs = new Dictionary<DateTime, int>()
{
    { new DateTime(2010, 01, 20, 19, 05, 00), 10 },
    { new DateTime(2010, 01, 20, 19, 05, 19), 11 },
    { new DateTime(2010, 01, 20, 19, 05, 49), 12 },
    { new DateTime(2010, 01, 20, 19, 06, 05), 13 },
    { new DateTime(2010, 01, 20, 19, 07, 05), 14 },
    { new DateTime(2010, 01, 20, 19, 07, 55), 15 },
};

我希望过滤的结果是:

<2010-01-20 19:05:00, 10>
<2010-01-20 19:06:05, 13>
<2010-01-20 19:07:05, 14>`
字典中的

DateTime键按升序排列,因此无需重新排序,但我需要它非常高效,因为需要处理大量数据。

你能介绍一些很好的LINQ查询吗?

2 个答案:

答案 0 :(得分:5)

我认为这对Linq来说是一个糟糕的候选人。我会选择一位直截了当的调查员:

public static IEnumerable<KeyValuePair<DateTime, int>> Filter(IEnumerable<KeyValuePair<DateTime, int>> values)
{
    KeyValuePair<DateTime, int>? previous = null;

    foreach (var kvp in values.OrderBy(v => v.Key))
    {
        if (previous == null || (kvp.Key - previous.Value.Key).TotalMinutes >= 1)
        {
            previous = kvp;
            yield return kvp;
        }
    }
}

然后只需枚举它,并根据结果做任何你需要的事情:

foreach (var value in Filter(dictionary))
{
    Console.WriteLine($"{value.Key} - {value.Value}");
}

只是为了好玩,一个Linq版本(请,请不要使用它):

public static IEnumerable<KeyValuePair<DateTime, int>> FilterLinq(IEnumerable<KeyValuePair<DateTime, int>> values)
{
    KeyValuePair<DateTime, int>? previous = null;

    return from kvp in values
           orderby kvp.Key
           where previous == null || (kvp.Key - previous.Value.Key).TotalMinutes >= 1
           select (previous = kvp).Value;
}

答案 1 :(得分:2)

我建议LINQ在这里是个不错的选择。它通常很容易维护,而且往往任何性能损失都可以忽略不计。

试试这个:

var filtered =
    pairs.Skip(1).Aggregate(pairs.Take(1).ToList(), (a, p) =>
    {
        if (p.Key.Subtract(a.Last().Key).TotalMinutes >= 1.0)
        {
            a.Add(p);
        }
        return a;
    }).ToList();

这给出了:

filtered