我有一个简单的DataTable如下:
column1 value1 value2
ee 1 2
ee 2 4
ee1 3 6
ee2 3 3
ee2 4 2
我希望每个colunm1得到value1和value2的总和,最后得到一个新的DataTable,如下所示:
column1 value1 value2
ee 3 6
ee1 3 6
ee2 7 5
它s not too difficult to realize by a loop of calculation in a traditional way.
I want to realize that as simple as possible in a Linq way.
I have a existed solution, but I don
非常喜欢它。特别是,在这里我不得不使用Foreach来实现它,它有点奇怪。
var resultDt = dtIn.Clone();
dtIn.Select().GroupBy(m=>m["column1"].ToString())
.Select(n=>new
{ Row = n.First(),
Value1 = n.Sum(s=>(int)s["value1"]),
Value2 = n.Sum(s=>(int)s["value2"])
})
.ToList()
.ForEach(m=>
{
var drNew = m.Row;
drNew["value1"] = m.Value1;
drNew["value2"] = m.Value2;
resultDt.Rows.Add(drNew);
});
有人可以给我一个暗示吗?
答案 0 :(得分:2)
var resultDt = dtIn.AsEnumerable().GroupBy(m=>m.Field<string>("column1"))
.Select(n=>new
{ column1 = n.Key,
Value1 = n.Sum(s=>s.Field<int>("value1")),
Value2 = n.Sum(s=>s.Field<int>("value2"))
}).CopyToDataTable();
答案 1 :(得分:1)
这里尝试一下,这应该适合你:
DataTable dt = new DataTable();
dt.Columns.Add("column1");
dt.Columns.Add("value1", typeof(int));
dt.Columns.Add("value2", typeof(int));
dt.Rows.Add("ee", 1, 2);
dt.Rows.Add("ee", 2, 4);
dt.Rows.Add("ee1", 3, 6);
dt.Rows.Add("ee2", 3, 3);
dt.Rows.Add("ee2", 4, 2);
var items = dt.AsEnumerable().GroupBy(
x => x.Field<string>("column1")
).Select
(
n => new
{
column1 = n.Key,
value1 = n.Sum(z => z.Field<int>("value1")),
value2 = n.Sum(z => z.Field<int>("value2"))
}
)
.ToList();
答案 2 :(得分:0)
更聪明的方法通常是在数据库端进行聚合以避免填充不必要的数据。
循环可以隐藏在.Aggregate
:
var result = dt.Rows.Cast<DataRow>().ToLookup(r => r[0] as string).Aggregate(dt.Clone(),
(t, g) => t.Rows.Add(g.Key, g.Sum(r => (int)r[1]), g.Sum(r => (int)r[2])).Table);
或多列更复杂:
DataTable result = dt.Rows.Cast<DataRow>().ToLookup(r => r[0])
.Aggregate(dt.Clone(), (t, g) => t.Rows.Add(Enumerable.Range(0, t.Columns.Count)
.Select(i => i < 1 ? g.Key : g.Sum(r => (int)r[i])).ToArray()).Table);
Debug.Print(string.Join("\t", result.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
Debug.Print(string.Join("\n", result.Rows.Cast<DataRow>().Select(r => string.Join("\t\t", r.ItemArray))));