3

我有这个简单的数据表:

 type (string)   |       cnt (int)     
_____________________________________
aaa                         1
aaa                         2
aaa                         10
bbb                         1
bbb                         1

我想生成1 个这样的匿名类型:

{
sumAAA= 13 , sumBBB=2  //13=1+2+10....
}

类似的东西:(伪代码)

var obj= dt.AsEnumerable().Select(f=> new { sumAAA =f.sumOfCntOfAaa , sumBBB =f.sumOfCntOfBbb });

有什么帮助吗?

编辑,这将帮助你

   DataTable dt = new DataTable("myTable");
    dt.Columns.Add("cnt", typeof (int));
    dt.Columns.Add("type", typeof (string));
    DataRow row = dt.NewRow();
    row["cnt"] = 1;
    row["type"] = "aaa";
    dt.Rows.Add(row);
    row = dt.NewRow();
    row["cnt"] = 2;
    row["type"] = "aaa";
    dt.Rows.Add(row);
    row = dt.NewRow();
    row["cnt"] = 10;
    row["type"] = "aaa";
    dt.Rows.Add(row);
    row = dt.NewRow();
    row["cnt"] = 1;
    row["type"] = "bbb";
    dt.Rows.Add(row);
    row = dt.NewRow();
    row["cnt"] = 1;
    row["type"] = "bbb";
    dt.Rows.Add(row);
4

4 回答 4

7

动态:

dynamic result = new ExpandoObject();
dt.AsEnumerable()
  .GroupBy(r => r.Field<String>("type"))
  .ToList()
  .ForEach(g=> ((IDictionary<String, Object>)result)["sum" + g.Key.ToUpper()] = g.Sum(r=>r.Field<Int32>("cnt")));

Console.WriteLine(result.sumAAA);
Console.WriteLine(result.sumBBB);

适用于任意数量的不同types,不仅aaabbb.

输出:

13
2

于 2012-07-25T13:20:59.907 回答
4

在程序集中,具有相同属性、相同类型和顺序的所有匿名类型都是相同类型。因此可以创建相同匿名类型的新实例:

第一版

var totals = new {
    SumAs = 0,
    SumBs = 0
};

var result = dt.AsEnumerable().Select(dr => {
    totals = new {
        SumAs = totals.SumAs + (dr["type"].Equals("aaa") ? (int)dr["cnt"] : 0),
        SumBs = totals.SumBs + (dr["type"].Equals("bbb") ? (int)dr["cnt"] : 0)
    };
    return totals;
}).Last();

但是用聚合一个可以做得更好......

版本二

var result2 = dt.AsEnumerable().Aggregate(new { SumAs = 0, SumBs = 0 }, (total, dr) => {
    return new {
        SumAs = total.SumAs + (dr["type"].Equals("aaa") ? (int)dr["cnt"] : 0),
        SumBs = total.SumBs + (dr["type"].Equals("bbb") ? (int)dr["cnt"] : 0)
    };
});

更新:使用版本 2 的完整示例

(使用元组是因为它们更容易设置):

粘贴到默认的 C# 控制台项目中:

using System;
using System.Linq;

class Program {
    static void Main(string[] args) {
        var input = Enumerable.Range(1, 10).Select(x => Tuple.Create(x, x*x));

        var res = input.Aggregate(new { Firsts = 0, Seconds = 0}, (total, val) => {
            return new {
                Firsts = total.Firsts + val.Item1,
                Seconds = total.Seconds + val.Item2
            };
        });

        Console.WriteLine("Firsts: {0}; Seconds: {1}", res.Firsts, res.Seconds);
    }
}
于 2012-07-25T13:15:28.770 回答
1

你有什么理由不想使用 2 LINQ 语句?

var obj = new {
    sumAAA = dt.Rows
        .Where(x => x["type"] == "aaa")
        .Sum(y => (int) y["cnt"]), 
    sumBBB = dt.Rows
        .Where(x => x["type"] == "bbb")
        .Sum(y => (int) y["cnt"])
};

还是一个简单的for循环?

int sAAA = 0; int sBBB = 0;

foreach (DataRow row in dt.Rows)
{
    if(row["type"] == "aaa")
        sAAA += (int) row["cnt"];
    else
        sBBB += (int) row["cnt"];
}

var obj = new { sumAAA = sAAA, sumBBB = sBBB };

编辑:哎呀......匿名对象是不可变的,相应地改变了我的答案

于 2012-07-25T13:14:58.413 回答
0
var list = dt.AsEnumerable()
          .GroupBy(row => row["type"])
          .Select(grp => new { Type = grp.Key, 
                             Sum = grp.Sum(c => (int)c["cnt"])
          });

这将为您提供一个匿名 {type, sum} 列表,这一定是一个好的开始!

于 2012-07-25T13:02:25.007 回答