2015年11月19日木曜日

.Net(VB C#) LINQ Aggregateを使用して集計する

LINQのAggregateを使用して、リストの値を集計します。

いつものごとく
テスト用の高級果物クラスです。
【C#】
private class Fruit
{
    public string Name { get; set; }
    public string Rank { get; set; }
    public decimal Price { get; set; }
}
【VB#】
Private Class Fruit
    Public Property Name As String
    Public Property Rank As String
    Public Property Price As Decimal
End Class
テストデータを作成します。
【C#】
var fruits = new List<Fruit>()
                {
                    new Fruit(){Name = "りんご", Rank = "A" , Price = 1000 },
                    new Fruit(){Name = "みかん", Rank = "A" , Price = 600 },
                    new Fruit(){Name = "ぶどう", Rank = "B" , Price = 1200 },
                    new Fruit(){Name = "りんご", Rank = "B" , Price = 800 },
                    new Fruit(){Name = "みかん", Rank = "A" , Price = 500 }

                };
【VB】
Dim fruits = New List(Of Fruit)() From
            {
                New Fruit() With {.Name = "りんご", .Rank = "A", .Price = 1000},
                New Fruit() With {.Name = "みかん", .Rank = "A", .Price = 600},
                New Fruit() With {.Name = "ぶどう", .Rank = "B", .Price = 1200},
                New Fruit() With {.Name = "りんご", .Rank = "B", .Price = 800},
                New Fruit() With {.Name = "みかん", .Rank = "A", .Price = 500}
            }
果物名別の合計金額を集計します。

まずはGroupByで名前でグループ化します。
つづいてグループ化した各アイテムに対してAgreegateで金額を集計します。
Agreegateの第1引数がseed(種)で、第二引数でseedに対して各アイテムのPriceを加算していきます。
【C#】
var nameSumPriceList = fruits
    .GroupBy(itm => itm.Name)
    .Select(grp =>
        new
        {
            Name = grp.Key,
            SumPrice = grp.Aggregate(0m, (seedSum, curItm) =>  seedSum += curItm.Price)
        });
//--出力--
// りんご 1800
// みかん 1100
// ぶどう 1200
nameSumPriceList.ToList().ForEach(itm =>
 { Console.WriteLine(string.Format("{0} {1}", itm.Name, itm.SumPrice)); });
【VB】
Dim nameSumPriceList = fruits _
            .GroupBy(Function(itm) itm.Name) _
            .Select(Function(grp) _
                        New With
                        {
                            .Name = grp.Key,
                            .SumPrice = grp.Aggregate(0D, Function(seedSum, curItm) seedSum + curItm.Price)
                        })
'--出力--
' りんご 1800
' みかん 1100
' ぶどう 1200
nameSumPriceList.ToList().ForEach(Sub(itm) _
  Console.WriteLine(String.Format("{0} {1}", itm.Name, itm.SumPrice)))

次は果物名別ランク別の最大金額を集計します。
【C#】
//名前別ランク別の最大金額          
var namePriceList = fruits
    .GroupBy(itm => new { itm.Name, itm.Rank })
    .Select(grp =>
        new
        {
            Name = grp.Key.Name,
            Rank = grp.Key.Rank,
            MaxPrice = 
                grp.Aggregate(0m, (seedMax, curItm) => 
                    (seedMax > curItm.Price) ? seedMax : curItm.Price)
        });

//--出力
// りんご A 1000
// みかん A 600
// ぶどう B 1200
// りんご B 800
namePriceList.ToList().ForEach(itm =>
    { Console.WriteLine(string.Format("{0} {1} {2}", itm.Name, itm.Rank, itm.MaxPrice)); });
【VB】
GroupByでグループ化のキーに匿名クラスを使用する際は、キーに使用するプロパティの前にKeyキーワードを付けます。
'名前ランク別の最大金額          
Dim namePriceList = fruits _
        .GroupBy(Function(itm) New With {Key itm.Name, Key itm.Rank}) _
        .Select(Function(grp) _
           New With
           {
               .Name = grp.Key.Name,
               .Rank = grp.Key.Rank,
               .MaxPrice = 
                   grp.Aggregate(0D, Function(seedMax, curItm) 
                       If(seedMax > curItm.Price, seedMax, curItm.Price))
           })

'--出力
' りんご A 1000
' みかん A 600
' ぶどう B 1200
' りんご B 800
namePriceList.ToList().ForEach(
    Sub(itm) Console.WriteLine(String.Format("{0} {1} {2}", itm.Name, itm.Rank, itm.MaxPrice)))

0 件のコメント: