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

アセンブリでは、同じタイプと順序の同じプロパティを持つすべての匿名タイプは同じタイプです。したがって、同じ匿名タイプの新しいインスタンスを作成することが可能です。

バージョン1

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

しかし、骨材を使用すると、より良い結果が得られます...

バージョン2

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 に答える