用linq多个和一个匿名类型?

时间:2012-07-25 12:57:55

标签: c# .net linq datatable

我有这个简单的数据表:

 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 个答案:

答案 0 :(得分:6)

充满活力:

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

适用于不同type s的豁免号码,不仅适用于aaabbb

<强>输出:

  

13
  2

答案 1 :(得分: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);
    }
}

答案 2 :(得分: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 };

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

答案 3 :(得分:0)

var list = dt.AsEnumerable()
          .GroupBy(row => row["type"])
          .Select(grp => new { Type = grp.Key, 
                             Sum = grp.Sum(c => (int)c["cnt"])
          });

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