2016-08-05 50 views
1

我已经创建了一个Datatable,我试图减少行数。我能够找到一种方法来检查表中是否存在testID并合并主机名,但我不确定如何删除源行。DataTable组合值和删除源行

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 

这里是我当前的功能合并主机名和testIDs当需要时

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的表。

仅供参考,这里是我的工作,整个数据表:

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 

回答

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相同的方式。

+0

非常完美,非常感谢!由于testID是字母数字,所以做了一些小修改,我将其更改为一个字符串,并且在我删除的'SetField(“description”...)'中有一个额外的空间。 – Chris

+0

有没有办法在加入字符串之前进行检查?换句话说,我希望有一些字段具有相同的ID,但来自不同的来源,我想合并来源,但只有唯一的来源? – Chris

+0

我尝试使用.Distinct(),但它给了我这个'System.Linq.Enumerable + d__63'1 [System.Char]'几次 – Chris