我有以下数据:
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的最小值。
答案 0 :(得分:2)
需要使用Aggregate这样的方法:
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.}
*/
测试数据:
var data = new[]{
new AtmRecord( 4, 1, 3, DateTime.Parse("2019-01-01 18:20"), DateTime.Parse("2019-01-01 18:45") ),
new AtmRecord( 4, 2, 5, DateTime.Parse("2019-01-01 18:25"), DateTime.Parse("2019-01-01 18:45") ),
new AtmRecord( 5, 3, 2, DateTime.Parse("2019-01-01 18:10"), DateTime.Parse("2019-01-01 18:45") ),
new AtmRecord( 5, 1, 2, DateTime.Parse("2019-01-01 18:00"), DateTime.Parse("2019-01-01 18:45") ),
new AtmRecord( 5, 6, 5, DateTime.Parse("2019-01-01 18:46"), DateTime.Parse("2019-01-01 18:50") )
};
其他类别:
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;
}
}
答案 1 :(得分:0)
您是否要像这样分组?
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