c#使用LiNQ删除Datatable中的多行

时间:2016-07-11 18:43:14

标签: c# linq datatable

这应该很简单,但我无法解决这个问题。我有一个数据表,其中包含名称,年龄,其中有行有学生姓名,但有多行特殊学生名称'克里斯'和约翰。最终结果应该有一个表格,其中除了Chris和John之外的所有行都将被组合成一行名为Other,其中包含其年龄的总和。

即。

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循环中,因为迭代更改。

2 个答案:

答案 0 :(得分:3)

I'd do that using Linq + delegate. Why? A solution with delegate is more elegant and more specific for such of case, because a name may starts with big or small letter. Check below solution:

//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});

Result:

NAME  AGE
Tom   20 
Peter 5 
Tom   33 
Other 37 

For further details, please see: Func Delegate

答案 1 :(得分:1)

你可以使用for循环来实现这个目的,比如

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