C# 如何按聚合进行分组?
我有以下数据:C# 如何按聚合进行分组?,c#,linq,group-by,overlapping,C#,Linq,Group By,Overlapping,我有以下数据: ATMID StatusId ComponentId FromDateTime ToDateTime 4 1 3 2019-01-01 18:20 2019-01-01 18:45 4 2 5 2019-01-01 18:25 2019-01-01 18:45 5 3 2 2019
ATMID StatusId ComponentId FromDateTime ToDateTime
4 1 3 2019-01-01 18:20 2019-01-01 18:45
4 2 5 2019-01-01 18:25 2019-01-01 18:45
5 3 2 2019-01-01 18:10 2019-01-01 18:45
5 1 2 2019-01-01 18:00 2019-01-01 18:45
5 6 5 2019-01-01 18:46 2019-01-01 18:50
我希望以这样一种方式进行汇总,其结果是:
Atmid St_Comp FromDateTime ToDateTime
4 {(1,3),(2,5)} 2019-01-01 18:20 2019-01-01 18:45
5 {(3,2),(1,2)} 2019-01-01 18:00 2019-01-01 18:45
5 {(6,5)} 2019-01-01 18:46 2019-01-01 18:50
如何使用Linq实现这一点
这是我的密码:
var grouped = Problem_Fact_Measure_Overalls.GroupBy(
i => new { i.ATMId},
i => new {i.ComponentId,i.StatusId},
(Atmid, St_Comp) => new { Atmid, St_Comp });
但我无法在FromDateTime的最小值上进行聚合。需要使用以下方法:
var result = data
.Aggregate(
new List<KeyValuePair<DateTimeRange, List<AtmRecord>>>(),
(accumulator, atmRecord) => {
var segment = accumulator.FirstOrDefault(
v => atmRecord.ATMID == v.Value.First().ATMID &&
atmRecord.FromDateTime <= v.Key.To &&
atmRecord.ToDateTime >= v.Key.From);
if (segment.Key == null)
{
accumulator.Add(new KeyValuePair<DateTimeRange, List<AtmRecord>>(
new DateTimeRange(atmRecord.FromDateTime, atmRecord.ToDateTime),
new List<AtmRecord>() {atmRecord}));
return accumulator;
}
if (atmRecord.FromDateTime < segment.Key.From)
{
segment.Key.From = atmRecord.FromDateTime;
}
if (atmRecord.ToDateTime > segment.Key.To)
{
segment.Key.To = atmRecord.ToDateTime;
}
segment.Value.Add(atmRecord);
return accumulator;
},
accumulator => {
return accumulator
.Select(v => new
{
Atmid = v.Value.First().ATMID,
St_Comp = v.Value
.Select(r => (r.StatusId, r.ComponentId))
.ToArray(),
FromDateTime = v.Key.From,
ToDateTime = v.Key.To
});
})
.ToArray();
/* result:
[0]:{ Atmid = 4, St_Comp = {(int, int)[2]}, FromDateTime = {2019-01-01 6:20:00 p.m.}, ToDateTime = {2019-01-01 6:45:00 p.m.} }
Atmid [int]:4
FromDateTime [DateTime]:{2019-01-01 6:20:00 p.m.}
St_Comp:{(int, int)[2]}
[0]:(1, 3)
[1]:(2, 5)
ToDateTime [DateTime]:{2019-01-01 6:45:00 p.m.}
[1]:{ Atmid = 5, St_Comp = {(int, int)[2]}, FromDateTime = {2019-01-01 6:00:00 p.m.}, ToDateTime = {2019-01-01 6:45:00 p.m.} }
Atmid [int]:5
FromDateTime [DateTime]:{2019-01-01 6:00:00 p.m.}
St_Comp:{(int, int)[2]}
[0]:(3, 2)
[1]:(1, 2)
ToDateTime [DateTime]:{2019-01-01 6:45:00 p.m.}
[2]:{ Atmid = 5, St_Comp = {(int, int)[1]}, FromDateTime = {2019-01-01 6:46:00 p.m.}, ToDateTime = {2019-01-01 6:50:00 p.m.} }
Atmid [int]:5
FromDateTime [DateTime]:{2019-01-01 6:46:00 p.m.}
St_Comp:{(int, int)[1]}
[0]:(6, 5)
ToDateTime [DateTime]:{2019-01-01 6:50:00 p.m.}
*/
其他类别:
internal sealed class AtmRecord
{
public int ATMID { get; }
public int StatusId { get; }
public int ComponentId { get; }
public DateTime FromDateTime { get; }
public DateTime ToDateTime { get; }
public AtmRecord(int aTMID, int statusId, int componentId, DateTime fromDateTime, DateTime toDateTime)
{
ATMID = aTMID;
StatusId = statusId;
ComponentId = componentId;
FromDateTime = fromDateTime;
ToDateTime = toDateTime;
}
}
internal sealed class DateTimeRange
{
public DateTime From { get; set; }
public DateTime To { get; set; }
public DateTimeRange(DateTime from, DateTime to)
{
From = from;
To = to;
}
}
你想这样分组吗
var grouped = Problem_Fact_Measure_Overalls.GroupBy(r => r.ATMID)
.Select(g => new
{
Atmid = g.Key,
St_Comp = g.Select(r => (r.StatusId, r.ComponentId)).ToArray(),
FromDateTime = g.Min(r => r.FromDateTime),
ToDateTime = g.Max(r => r.ToDateTime)
});
输出:
4 (1, 3), (2, 5) 2019-01-01 18:20 2019-01-01 18:45
5 (3, 2), (1, 2), (6, 5) 2019-01-01 18:00 2019-01-01 18:50
那么,你想把它们分成两(对)组?你尝试了什么?这不仅仅是严格的分组,你有两行用于Atmid=5。我猜这是因为最后一个的fromDate>ToDate?请用你已经做过的努力完整地说明你的问题。为什么要重叠标签?基于这一点输入很难获得你需求的参数。请更具体地说明你想要实现什么,你已经尝试了什么,以及你在哪里遇到了困难。现在它的意思是“请为我做这件事”。
4 (1, 3), (2, 5) 2019-01-01 18:20 2019-01-01 18:45
5 (3, 2), (1, 2), (6, 5) 2019-01-01 18:00 2019-01-01 18:50