我有一个使用以下类
创建的错误列表MyBugList
internal class BugDetails
{
public int Id { get; set; }
public string State { get; set; }
public string Severity { get; set; }
}
我想根据State
和Severity
对这些错误进行分组。我使用以下代码来实现它。
var BugListGroup = (from bug in MyBugList
group bug by new
{
bug.State,
bug.Severity
} into grp
select new
{
BugState = grp.Key.State,
BugSeverity = grp.Key.Severity,
BugCount = grp.Count()
}).OrderBy(x=> x.BugState).ToList();
这个linq查询给我输出如下
Closed Critical 40
Active Critical 167
Closed Medium 819
Closed Low 323
Resolved Medium 61
Resolved Low 11
Closed High 132
Active Low 17
Active Medium 88
Active High 38
Resolved High 4
Resolved Critical 22
Deferred High 11
但是我希望得到如下的输出
Critical High Medium Total
Closed 3 4 5 12
Active 5 4 5 14
Resolved 6 4 5 15
Deferred 1 4 5 10
Total 15 16 20 51
是否可以通过MyBugList
或BugListGroup
我想把输出作为一个列表,这样我就可以做到 提供数据网格。
注意:State和Severity值是动态的,不能进行硬编码
以下是Dmitriy Zapevalov提供的答案
的实施方法private void button1_Click(object sender, EventArgs e)
{
var grouped = MyBugList.GroupBy(b => b.State).Select(stateGrp => stateGrp.GroupBy(b => b.Severity));
//Setting DataGrid properties
dataGridBug.Rows.Clear();
dataGridBug.Columns.Clear();
dataGridBug.DefaultCellStyle.NullValue = "0";
dataGridBug.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;
//Declaring DataGrid Styles
var gridBackColor = Color.AliceBlue;
var gridFontStyle = new Font(Font, FontStyle.Bold | FontStyle.Italic);
//Declaring column and row Ids
const string stateColumnId = "State";
const string totalColumnId = "Total";
const string totalRowId = "Total";
//Adding first column
dataGridBug.Columns.Add(stateColumnId, stateColumnId);
dataGridBug.Columns[0].DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleLeft;
//Adding other columns
foreach (var strSeverity in MyBugList.Select(b => b.Severity).Distinct())
{
dataGridBug.Columns.Add(strSeverity, strSeverity);
}
//Adding Total Column
var totColPos = dataGridBug.Columns.Add(totalColumnId, totalColumnId);
var totCol = dataGridBug.Columns[totColPos];
//Adding data to grid
foreach (var state in grouped)
{
var nRow = dataGridBug.Rows.Add();
var severities = state as IList<IGrouping<string, BugDetails>> ?? state.ToList();
dataGridBug.Rows[nRow].Cells[0].Value = severities.First().First().State;
var sevCount = 0;
foreach (var severity in severities)
{
dataGridBug.Rows[nRow].Cells[severity.Key].Value = severity.Count();
sevCount += severity.Count();
}
dataGridBug.Rows[nRow].Cells[totalColumnId].Value = sevCount;
}
//Adding total row
var totRowPos = dataGridBug.Rows.Add(totalRowId);
var totRow = dataGridBug.Rows[totRowPos];
//Adding data to total row
for (var c = 1; c < dataGridBug.ColumnCount; c++)
{
var sum = 0;
for (var i = 0; i < dataGridBug.Rows.Count; ++i)
{
sum += Convert.ToInt32(dataGridBug.Rows[i].Cells[c].Value);
}
dataGridBug.Rows[totRowPos].Cells[c].Value = sum;
}
//Styling total column
totCol.DefaultCellStyle.BackColor = gridBackColor;
totCol.DefaultCellStyle.Font = gridFontStyle;
//Styling total row
totRow.DefaultCellStyle.BackColor = gridBackColor;
totRow.DefaultCellStyle.Font = gridFontStyle;
}
答案 0 :(得分:3)
你可以这样做(它是动态解决方案,你不需要硬编码任何东西)。 Details
类的BugModel
属性包含所有列 Critical , High 等等:
public class BugModel
{
public string BugState { get; set; }
public Dictionary<string, int> Details { get; set; }
public int Total { get { return Details.Sum(x => x.Value); } }
}
<强>解决方案:强>
var result = (from bug in BugListGroup
group bug by bug.BugState into sub
select new BugModel
{
BugState = sub.Key,
Details = sub.GroupBy(x => x.BugSeverity)
.ToDictionary(x => x.Key, x => x.Sum(y => y.BugCount))
}).ToList();
答案 1 :(得分:1)
我做过双重分组:
class Program
{
internal class BugDetails
{
public int Id { get; set; }
public string State { get; set; }
public string Severity { get; set; }
}
static void Main(string[] args)
{
var MyBugList = new BugDetails[]
{
new BugDetails() { Id = 1, State = "Active", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Closed", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Closed", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Closed", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Resolved", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Resolved", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Resolved", Severity = "Critical" },
new BugDetails() { Id = 1, State = "Active", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Active", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Closed", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Closed", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Resolved", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Resolved", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Resolved", Severity = "Medium" },
new BugDetails() { Id = 1, State = "Active", Severity = "High" },
new BugDetails() { Id = 1, State = "Active", Severity = "High" },
new BugDetails() { Id = 1, State = "Closed", Severity = "High" },
new BugDetails() { Id = 1, State = "Closed", Severity = "High" },
new BugDetails() { Id = 1, State = "Closed", Severity = "High" },
new BugDetails() { Id = 1, State = "Closed", Severity = "High" },
new BugDetails() { Id = 1, State = "Closed", Severity = "High" },
};
var grouped = MyBugList.GroupBy(b => b.State).
Select(stateGrp => stateGrp.GroupBy(b => b.Severity));
foreach (var state in grouped)
{
Console.Write("{0}: ", state.First().First().State);
foreach (var severity in state)
{
Console.Write("{0}={1} ", severity.Key, severity.Count());
}
Console.WriteLine();
}
}
}
输出:
Active: Critical=1 Medium=2 High=2
Closed: Critical=3 Medium=2 High=5
Resolved: Critical=3 Medium=3
如果要使用DataGridView显示数据在这种情况下,您可以使用自己的属性集动态创建类型。但这种方式很复杂。 最简单(也是更多性能)的方法是手动填充DataGridView:
private void button1_Click(object sender, EventArgs e)
{
var grouped = MyBugList.GroupBy(b => b.State).
Select(stateGrp => stateGrp.GroupBy(b => b.Severity));
dataGridView1.Columns.Add("State", "State");
foreach (var strSeverity in MyBugList.Select(b => b.Severity).Distinct())
dataGridView1.Columns.Add(strSeverity, strSeverity);
foreach (var state in grouped)
{
int nRow = dataGridView1.Rows.Add();
dataGridView1.Rows[nRow].Cells[0].Value = state.First().First().State;
foreach (var severity in state)
{
dataGridView1.Rows[nRow].Cells[severity.Key].Value = severity.Count();
}
}
}