给出一个如下所示的集合:
[
{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等?
答案 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