2016-08-05 49 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