2016-07-11 73 views
1

這應該很簡單,但我無法弄清楚。我有一個Datatable,它具有名稱,年齡,其中有行的學生名稱,但然後多行特殊學生'姓名'克里斯和約翰的。最終結果應該有一個表,除了Chris和John之外的所有行都會被合併到一個名爲Other的行中,並與他們的年齡相加。c#使用LiNQ刪除Datatable中的多行

即。

NAME | AGE 
Tom | 20 
John | 15 
Peter | 5 
John | 2 
Tom | 33 
Chris | 20 

最終結果是:

NAME | AGE 
Tom | 20 
Peter | 5 
Tom | 33 
Other | 37 

這是即時通訊做現在:

var others = table.AsEnumerable().Where(x => x["NAME"].ToString().Equals("Chris") || x["NAME"].ToString().Equals("John")); 
var tmpOthers = 0; 
foreach (DataRow otherRow in others) 
      tmpOthers += decimal.Parse(otherRow["AGE"].ToString()); 
table = table.AsEnumerable().Where(x => !x["NAME"].ToString().Equals("Chris") || !x["NAME"].ToString().Equals("John")).CopyToDataTable(); 
table.Add(//OTHER-ROW-Here) 

這工作,但我知道必須有一個單一的LINQ做到這一點更簡單的方法聲明。我也無法將table.Rows.Remove放在同一個for循環中,因爲迭代更改。

+0

RemoveRange? https://msdn.microsoft.com/zh-tw/library/system.data.entity.dbset.removerange(v=vs.113).aspx – MichaelMao

+0

「name」是否始終以大寫字母開頭? –

回答

2

我做的是使用LINQ +委託。爲什麼?對於這種情況,使用委託的解決方案更加優雅,更具體,因爲名稱可能以大或小的字母開頭。檢查下面的解決方案:

//delegate to return "Other" for {"Chris","John"} - ignoring case 
Func<string, string> GetOtherName = delegate(string s) 
    { 
     if(string.Equals(s, "Chris", StringComparison.OrdinalIgnoreCase) || 
       string.Equals(s, "John", StringComparison.OrdinalIgnoreCase)) 
      return "Other"; 
     else 
      return s; 
    }; 

//get total age for "Other" 
var otherAge = dt.AsEnumerable() 
      .Where(x=>GetOtherName(x.Field<string>("NAME")) == "Other") 
      .Select(x=>x.Field<int>("AGE")).Sum(); 

//remove "Other" rows 
dt.AsEnumerable() 
    .Where(x=>GetOtherName(x.Field<string>("NAME")) == "Other") 
    .ToList() 
    .ForEach(r=>r.Delete()); 

//finally add "other" row 
dt.Rows.Add(new object[]{"Other", otherAge}); 

結果:

NAME AGE 
Tom 20 
Peter 5 
Tom 33 
Other 37 

欲知詳情,請訪問:Func Delegate

+1

超級!這太清潔了!喜歡編碼風格 –

1

那麼你可以使用一個for循環爲目的像

for(int i=0; i<others.Count(); i++) 
    table.Rows.Remove(others[i]); 
+0

它與for循環一起工作,但我給出的代碼有點混亂,我知道應該有一種方法將所有這些邏輯寫入單個LiNQ語句中。類似於table.AsEnumerable()。Where(x => x [「NAME」]。ToString()。Equals(「Chris」)|| x [「NAME」]。ToString()。Equals(「John」) )(總結一些局部變量中的AGE)。刪除這些行.CopyToTable()'這樣的邏輯 –

+0

@ civic.sir在我看來,巨大的linq語句比你原來的代碼更混亂。你可以在.Where()結果集上做一個.ForEach(),但我不確定如何在那之後再次在那個Where()上移除Range。 – dckuehn

+0

@dckuehn是的,這就是我尋找.. .ForEach()。哪裏,然後我可以簡單地做一個copytoDataTable()在最後沒有? –