アイテム(ID int、Done int、Total int)というテーブルがあるとしましょう。
2つのクエリで実行できます。
int total = m.Items.Sum(p=>p.Total)
int done = m.Items.Sum(p=>p.Done)
しかし、次のような1つのクエリでそれを行いたいと思います。
var x = from p in m.Items select new { Sum(p.Total), Sum(p.Done)};
確かに、LINQ構文から集計関数を呼び出す方法はありますか?
これはトリックを行います:
from p in m.Items
group p by 1 into g
select new
{
SumTotal = g.Sum(x => x.Total),
SumDone = g.Sum(x => x.Done)
};
テーブルを合計するには、定数でグループ化します。
from p in m.Items
group p by 1 into g
select new {
SumTotal = g.Sum(x => x.Total),
SumDone = g.Sum(x => x.Done)
}
どう?
m.Items.Select(item => new { Total = item.Total, Done = item.Done })
.Aggregate((t1, t2) => new { Total = t1.Total + t2.Total, Done = t1.Done + t2.Done });
私が作成した変数がIqueryableであることを思い出すまで、コードの残りの部分で合計またはその他の集計を抽出する場所を把握することは私を混乱させました。データベースにOrderで構成されるテーブルがあり、ABC会社の概要を作成するとします。
var myResult = from g in dbcontext.Ordertable
group p by (p.CUSTNAME == "ABC") into q // i.e., all of ABC company at once
select new
{
tempPrice = q.Sum( x => (x.PRICE ?? 0m) ), // (?? makes sure we don't get back a nullable)
tempQty = q.Sum( x => (x.QTY ?? 0m) )
};
楽しい部分-tempPriceとtempQtyはどこにも宣言されていませんが、myResultの一部である必要がありますか?次のようにアクセスします。
Console.Writeline(string.Format("You ordered {0} for a total price of {1:C}",
myResult.Single().tempQty,
myResult.Single().tempPrice ));
他の多くのQueryableメソッドも使用できます。
ヘルパーTupleクラスを使用すると、独自のクラス、または.NET 4では、これを行うことができる標準クラスを使用できます。
var init = Tuple.Create(0, 0);
var res = m.Items.Aggregate(init, (t,v) => Tuple.Create(t.Item1 + v.Total, t.Item2 + v.Done));
res.Item1
は、Total
列とDone
列のres.Item2
の合計です。
//Calculate the total in list field values
//Use the header file:
Using System.Linq;
int i = Total.Sum(G => G.First);
//By using LINQ to calculate the total in a list field,
var T = (from t in Total group t by Total into g select g.Sum(t => t.First)).ToList();
//Here Total is a List and First is the one of the integer field in list(Total)
これはすでに回答済みですが、他の回答はコレクションに対して複数回の反復(Sumへの複数の呼び出し)を行うか、多数の中間オブジェクト/タプルを作成しますが、そうでない場合は、拡張機能を作成できます昔ながらの方法(または複数)を実行しますが、LINQ式にうまく適合します。
このような拡張メソッドは次のようになります。
public static Tuple<int, int> Sum<T>(this IEnumerable<T> collection, Func<T, int> selector1, Func<T, int> selector2)
{
int a = 0;
int b = 0;
foreach(var i in collection)
{
a += selector1(i);
b += selector2(i);
}
return Tuple.Create(a, b);
}
そして、次のように使用できます。
public class Stuff
{
public int X;
public int Y;
}
//...
var stuffs = new List<Stuff>()
{
new Stuff { X = 1, Y = 10 },
new Stuff { X = 1, Y = 10 }
};
var sums = stuffs.Sum(s => s.X, s => s.Y);
C#7. で導入されたタプルの言語サポートを使用すると、次のLINQ式を使用してこれを解決できます。
var itemSums = m.Items.Aggregate((Total: 0, Done: 0), (sums, item) => (sums.Total + item.Total, sums.Done + item.Done));
完全なコードサンプル:
var m = new
{
Items = new[]
{
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
new { Total = 10, Done = 1 },
},
};
var itemSums = m.Items.Aggregate((Total: 0, Done: 0), (sums, item) => (sums.Total + item.Total, sums.Done + item.Done));
Console.WriteLine($"Sum of Total: {itemSums.Total}, Sum of Done: {itemSums.Done}");