我创建了一个Datatable,我试图减少行数。我能够找到一种方法来检查表中是否存在testID并合并主机名但我不确定如何删除源行。
示例dtOrginal
:
testID passFail description hostname
1ab pass .... alpha
1ab pass .... bravo
1ab fail .... charlie
1ac pass .... alpha
当前结果示例:
testID passFail description hostname
1ab pass .... alpha, bravo
1ab pass .... bravo
1ab fail .... charlie
1ac pass .... alpha
我想要的是什么
testID passFail description hostname
1ab pass .... alpha, bravo
1ab fail .... charlie
1ac pass .... alpha
这是我当前在必要时合并主机名和testID的函数
DataTable dtReducedColumns = CombineHostnames(dtOrinal).Copy();
private static DataTable CombineHostnames(DataTable dt)
{
for (int i = 0; i < dtOrginal.Rows.Count; i++)
{
bool isDupe = false;
string a, b, c, d, e, f, g, h, k, l;
for (int j = 0; j < dt.Rows.Count; j++)
{
a = dtOrginal.Rows[i][0].ToString(); //testID
b = dt.Rows[j][0].ToString();
c = dtOrginal.Rows[i][1].ToString(); //passFail
d = dt.Rows[j][1].ToString();
g = dtOrginal.Rows[i][2].ToString(); //description
h = dt.Rows[j][2].ToString();
if (a == b && c == d && g == h)
{
e = dt.Rows[j][10].ToString();
f = dtOrginal.Rows[i][10].ToString(); //hostname
k = dtOrginalRows[i][8].ToString(); //source
l = dt.Rows[j][8].ToString();
if (!e.Contains(f))
dt.Rows[j][10] = e + ", " + f; //combine hostnames
if (!k.Contains(l))
dt.Rows[j][8] = k + ", " + l; //combine sources
isDupe = true;
//tried adding dt.Rows[j].Delete() here
//tried adding dt.Rows[j-1].Delete() here get -1 error
break;
}
//tried adding dt.Rows[j].Delete() here
//tried adding dt.Rows[j-1].Delete() here get -1 error
}
//tried adding dt.Rows[j].Delete() here
//tried adding dt.Rows[j-1].Delete() here get -1 error
if (!isDupe)
{
dt.ImportRow(dtOrginal.Rows[i]);
}
}
return dt;
}
我尝试删除行的地方会引发IndexOutOfBounds
异常或返回类似于dtOrginal
的表格。
供参考,以下是我使用的整个DataTable:
dtChecklistFindingsTable = new DataTable(); //Column Number
dtChecklistFindingsTable.Columns.Add("testID", typeof(string)); // 0
dtChecklistFindingsTable.Columns.Add("passFail", typeof(string)); // 1
dtChecklistFindingsTable.Columns.Add("description", typeof(string)); // 2
dtChecklistFindingsTable.Columns.Add("vulLevel", typeof(string)); // 3
dtChecklistFindingsTable.Columns.Add("recommendation", typeof(string)); // 4
dtChecklistFindingsTable.Columns.Add("comments", typeof(string)); // 5
dtChecklistFindingsTable.Columns.Add("title", typeof(string)); // 6
dtChecklistFindingsTable.Columns.Add("testCheck", typeof(string)); // 7
dtChecklistFindingsTable.Columns.Add("source", typeof(string)); // 8
dtChecklistFindingsTable.Columns.Add("date", typeof(string)); // 9
dtChecklistFindingsTable.Columns.Add("hostName", typeof(string)); // 10
dtChecklistFindingsTable.Columns.Add("os", typeof(string)); // 11
dtChecklistFindingsTable.Columns.Add("ipAddr", typeof(string)); // 12
dtChecklistFindingsTable.Columns.Add("stigLevel", typeof(string)); // 13
dtChecklistFindingsTable.Columns.Add("stigSeverity", typeof(string)); // 14
dtChecklistFindingsTable.Columns.Add("sarStatus", typeof(string)); // 15
dtChecklistFindingsTable.Columns.Add("iaControl", typeof(string)); // 16
答案 0 :(得分:1)
这是Linq-To-DataTable
的一个很好的用例,尤其是Enumerable.GroupBy
+ String.Join
:
private static DataTable CombineHostnames(DataTable dtOrginal)
{
DataTable tblresult = dtOrginal.Clone(); // empty table, same columns
var rowGroups = dtOrginal.AsEnumerable()
.GroupBy(row => new
{
Id = row.Field<string>("testId"),
passFail = row.Field<string>("passFail")
});
foreach (var group in rowGroups)
{
DataRow row = tblresult.Rows.Add(); // already added now
row.SetField("testId", group.Key.Id);
row.SetField("passFail", group.Key.passFail);
row.SetField("description", group.First()["description"]); // the first?
string hostNames = String.Join(", ", group.Select(r => r.Field<string>("hostname")));
row.SetField("hostname", hostNames);
}
return tblresult;
}
您可以通过简单地使用每个组中的第一个或其他逻辑,以与我已添加description
相同的方式添加其他列。