如何以较小的时间增量过滤集合?

时间:2017-12-31 18:32:34

标签: c# .net linq

给出一个如下所示的集合:

[
{Price:123.45, DateTime:01/01/18 12:01:10}
{Price:89.23, DateTime:01/01/18 12:01:20}
{Price:66.13, DateTime:01/01/18 12:01:30}
{Price:75.00, DateTime:01/01/18 12:02:45}
]

如何使用linq过滤此集合,仅包含最接近每分钟开头的第一个数据项?例如,我想将上面的集合转换为以下集合:

[
{Price:123.45, DateTime:01/01/18 12:01:10}
{Price:75.00, DateTime:01/01/18 12:02:45}
]

此外,我如何实现类似的解决方案,但我不想过滤集合以包含最接近每分钟开始的第一个数据项,我想包括最接近每个5分钟间隔开始的第一个数据项?例如,最近的数据项是12:00,12:05,12:10等?

1 个答案:

答案 0 :(得分:1)

第一个问题最简单的解决方案是:

items.GroupBy(x => x.DateTime.AddSeconds(-x.DateTime.Second))
     .Select(x => x.OrderBy(i => i.DateTime).First());

然后我尝试制作可重复使用的解决方案,让您设置任何时间间隔:

public static IEnumerable<Item> ClosestTo(IEnumerable<Item> items, TimeSpan interval)
{
    return items.GroupBy(item =>
    {
        // Find a date that is closest to the start of interval.
        var ticksFloor = item.DateTime.Ticks - (item.DateTime.Ticks % interval.Ticks);
        return new DateTime(ticksFloor);
    }).Select(grouping => grouping.OrderBy(item => item.DateTime).First());
}

示例:

var items = new List<Item>
{
    new Item { DateTime = DateTime.Parse("01/01/18 12:01:10") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:01:20") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:01:30") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:02:45") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:05:00") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:07:30") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:09:00") },
    new Item { DateTime = DateTime.Parse("01/01/18 12:14:00") }
};

foreach (var item in ClosestTo(items, TimeSpan.FromMinutes(5)))
{
    Console.WriteLine($"DateTime: {item.DateTime}");
}

输出结果为:

  

DateTime:01.01.2018 12:01:10
  日期时间:01.01.2018 12:05:00
  日期时间:01.01.2018 12:14:00