选择舍入的时间值

问题描述 投票:0回答:2

我有这样的对象列表:

+-------------+------------+---------------------+
| ID          | Value      | Time                | 
+-------------+------------+---------------------+
| 1           | 1          | 2019-03-07 20:05:35 |
| 2           | 2          | 2019-03-07 20:06:09 |  
| 5           | 5          | 2019-03-07 20:11:27 |
| 7           | 1          | 2019-03-07 20:13:30 |
| 8           | 0          | 2019-03-07 20:13:41 |
| 7           | 1          | 2019-03-07 20:17:00 |
| 8           | 0          | 2019-03-07 20:22:20 |
| 7           | 1          | 2019-03-07 20:23:05 |
| 8           | 0          | 2019-03-07 20:27:35 |
| 7           | 1          | 2019-03-07 20:27:37 |
| 8           | 0          | 2019-03-07 20:28:01 |
| 7           | 5          | 2019-03-07 20:37:19 |
| 8           | 0          | 2019-03-07 20:37:27 |
| 7           | 1          | 2019-03-07 20:37:54 |
| 8           | 0          | 2019-03-07 20:40:11 |
| 7           | 1          | 2019-03-07 20:44:00 |
| 8           | 3          | 2019-03-07 20:45:00 |
| 7           | 1          | 2019-03-07 20:47:41 |
| 7           | 1          | 2019-03-07 20:48:43 |
| 7           | 1          | 2019-03-07 20:48:51 |
| 8           | 0          | 2019-03-07 20:51:11 |
| 8           | 0          | 2019-03-07 20:54:46 |
| 8           | 0          | 2019-03-07 20:55:36 |
+-------------+------------+---------------------+

如何选择相隔15/30分钟的记录并四舍五入时间并取最接近四舍五入时间的第一个值?

结果应该是这样的:

+-------------+------------+---------------------+
| ID          | Value      | Time                | 
+-------------+------------+---------------------+
| 1           | 1          | 2019-03-07 20:00:00 |
| 8           | 0          | 2019-03-07 20:15:00 |
| 7           | 5          | 2019-03-07 20:30:00 |
| 8           | 3          | 2019-03-07 20:45:00 |
+-------------+------------+---------------------+

到目前为止,我有这个:

List<Dates> SortedList = dates.OrderBy(o => o.Time).ToList();
var datax = SortedList.GroupBy(cd => new {
Date = cd.Time.AddSeconds(-cd.Time.Second)
       .AddMinutes(-cd.Time.Minute % 15),
        CounterName = cd.Time,
        Value = cd.Value
        }).Select(g =>new {
        Date = g.Key.Date,
        CounterName = g.Key.CounterName,
        Value = g.Key.Value                
});
c# linq
2个回答
1
投票

您可以尝试GroupBy,唯一的困难是实施分组标准:

 private static DateTime RoundToMinutes(DateTime value, int threshold = 15) {
   var shift = threshold * 
    (int)((value - value.Date).TotalMinutes / threshold +
          ((value - value.Date).TotalMinutes % threshold >= threshold / 2.0 ? 1 : 0));

   return value.Date.AddMinutes(shift);
 }

如果我们想要键的closest项,我们也必须实现ArgMin

代码:

 var result = list
   .GroupBy(item => RoundToMinutes(item.Date, 15))
   .Select(group => new {
      at   = group.Key,
      best = group.Aggregate((s, a) => 
        Math.Abs((s.Time - group.Key).TotalSeconds) < Math.Abs((a.Time - group.Key).TotalSeconds)) 
         ? s 
         : a) 
    })
   .Select(group => new MyObject() {
      ID    = group.at,
      Value = group.best.Value,
      Time  = group.best.Key
    }) 
   .ToList(); // materialization if required

0
投票

首先,创建一个将返回给定DateTime的最近四分之一的方法>

public static DateTime NearestQuarter(DateTime value)
{
    var temp = value.AddMinutes(7).AddSeconds(30);
    return new DateTime(temp.Year, temp.Month, temp.Day, temp.Hour, (temp.Minute / 15) * 15, 0);
}

然后您可以按NearestQuarter值将记录分组:

var groupedByNearestQuarter = records.GroupBy(r => NearestQuarter(r.Time));

最后,您要按距最近的四分之一的距离排序该组,对于最近的四分之一,请返回一个以最近的四分之一为时间的新记录。您可以使用foreach或LINQ查询,例如:

var nearestQuarterRecord = records.GroupBy(
    r => NearestQuarter(r.Time),
    r => r,
    (quarter, group) => {
        var nearestRecord = group.OrderBy(r => Math.Abs((r.Time - quarter).TotalSeconds)).First();
        return new Record() { Id = nearestRecord.Id, Value = nearestRecord.Value, Time = quarter };
    });
© www.soinside.com 2019 - 2024. All rights reserved.