尝试使用linq透视数据
本文关键字:透视 数据 linq | 更新日期: 2023-09-27 18:27:45
我有以下类结构:
public class TaskLog
{
public DateTime LogDate { get; set; }
public string Robot { get; set; }
public string Task { get; set; }
public Enums.ProbeDataState State { get; set; }
public TaskLog()
{
}
}
我创建了一个通用列表如下:
List<TaskLog> Logs;
我的输出:
Robot Date State
---------------------------------------------
aaa 8/5/2013 12:00:00 AM Task:1=fileDeltaFailed
aaa 8/5/2013 12:00:00 AM Task:2=fileDeltaFailed
aaa 8/5/2013 12:00:00 AM Task:4=fileDeltaFailed
bbb 8/5/2013 12:00:00 AM Task:1=fileDeltaFailed
bbb 8/5/2013 12:00:00 AM Task:2=fileDeltaFailed
bbb 8/5/2013 12:00:00 AM Task:4=fileDeltaFailed
然而,我想将任务和状态分组如下:
Tasks
Robot Date 1 2 4
aaa 8/5/2013 12:00:00 AM fileDeltaFailed fileDeltaFailed fileDeltaFailed
bbb 8/5/2013 12:00:00 AM fileDeltaFailed fileDeltaFailed fileDeltaFailed
我试着使用groupby,但没有成功,结果被卡住了。
例如
var dataQuery = Logs.Where(w => w.LogDate >= start && w.LogDate <= finish).GroupBy(g => g.LogDate).Select(t => new
{
LogDate = t.Key,
Details = t.OrderBy(o => o.Robot)
}).ToList();
如果我理解这个问题,你需要每个机器人的任务到状态的映射。您可以按Robot分组,并为每组选择一个字典:
Logs.GroupBy(t => t.Robot).Select(g => new {
Robot = g.Key,
TaskStates = g.ToDictionary(t => t.Task, t => t.State)
})
这假设任务名称对于每个机器人都是唯一的(否则ToDictionary
将抛出异常)。
您还可以为日期添加另一个级别的分组:
Logs.GroupBy(t => t.LogDate).Select(g => new {
Date = g.Key,
Details = g.GroupBy(t => t.Robot).Select(g => new {
Robot = g.Key,
TaskStates = g.ToDictionary(t => t.Task, t => t.State)
}).ToList()
})
注意,Details
属性本质上等同于我的第一个示例,唯一的区别是它查询外部分组,而不是整个序列。结果是{Date,Details}的序列,其中每个"Details"都是{Robot,TaskStates}的列表。
我还没有测试过这个,所以如果有我遗漏的bug,请告诉我。
var result = Logs.GroupBy(x=> new {x.Robot, x.Date})
.Select(g=> {
var a = g.ToList();
return
new {
a[0].Robot,
a[0].Date,
Task1 = a[0].State,
Task2 = a[1].State,
Task4 = a[2].State
};
});
假设您必须定义一个固定数量的Tasks
,为了使其更安全,我们可以这样做:
var result = Logs.GroupBy(x=> new {x.Robot, x.Date})
.Select(g=> {
var c = g.Count();
var a = g.ToList();
return
new {
a[0].Robot,
a[0].Date,
Task1 = a[0].State,
Task2 = c > 1 ? a[1].State : "",
Task4 = c > 2 ? a[2].State : ""
};
});
试试这个:
var newData = from w in Logs
where w.LogDate >= start && w.LogDate <= finish
group w by w.LogDate into g
select new
{
LogDate = g.Key,
Details = g.ToList().OrderBy(o => o.Robot)
};
查询newData
包含具有LogDate和Detais(按Robot排序的任务列表)的对象列表。