我有这样的对象列表:
+-------------+------------+---------------------+
| 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
});
您可以尝试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
首先,创建一个将返回给定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 };
});