DataTable组合值并删除源行

本文关键字:删除 组合 DataTable | 更新日期: 2023-09-27 18:01:12

我已经创建了一个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

这是我目前的功能,在必要时合并主机名和测试ID

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

DataTable组合值并删除源行

这是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一样添加其他列,只需使用每组中的第一个或通过另一个逻辑即可。