環境
- VB.NET
- .NET Framework 4.6
VB.NETでLINQのグループ化(SUM)
VB.NETでGroupByのLINQの書き方を調べても全然ヒットしないので覚書。
特にメソッドのLINQは少ないので困る。
難しい話は置いておいて結論から先に、複数キーでグループ化するには、
-
New With
じゃなくてTuple.Create
を使用する。
Dim group = details.GroupBy(Function(g) Tuple.Create(g.Item, g.category))
-
New With
ならKey
を付ける
Dim group = details.GroupBy(Function(g) new with{ Key g.Item, Key g.category})
テストで使用したリストの型
Item,Category,Quantityをもつリストを作成して、
Item,Categoryをグループ化、Quantityを合計する。
リストは以下の型クラス。
Class Items
Public Property Item As String
Public Property category As String
Public Property Quantity As Integer
Public Sub New(item As String, category As String, quantity As Integer)
Me.Item = item
Me.category = category
Me.Quantity = quantity
End Sub
End Class
匿名型でGroupByをしてみる
ネットで漁ってC#例からVB.NETに書き換えてみた。
Hogehoge()すると一応LINQは動くのだけど、期待通りの結果にならない。
Public Sub Hogehoge()
Dim details As New List(Of Items)
details.Add(New Items("A", "CateA", 1))
details.Add(New Items("A", "CateA", 2))
details.Add(New Items("B", "CateB", 1))
Dim group = details.GroupBy(Function(g) New With(g.Item, g.category)).
Select(Function(x) New With {.groupItem = x.Key.Item1, .groupCategory = x.Key.Item2, .sumQuantity = x.Sum(Function(s) s.Quantity)}).
ToList
For Each item In group
Debug.WriteLine(item.groupItem & ", " & item.groupCategory & ", " & item.sumQuantity)
Next
'A, CateA, 1
'A, CateA, 2 ' AのItemが3の1行になることを期待してた。
'B, CateB, 1
End Sub
Tuple.Createを使う
New With
の代わりにTuple.Create
を使用すると期待通り。
Public Sub Hogehoge()
Dim details As New List(Of Items)
details.Add(New Items("A", "CateA", 1))
details.Add(New Items("A", "CateA", 2))
details.Add(New Items("B", "CateB", 1))
Dim group = details.GroupBy(Function(g) Tuple.Create(g.Item, g.category)).
Select(Function(x) New With {.groupItem = x.Key.Item1, .groupCategory = x.Key.Item2, .sumQuantity = x.Sum(Function(s) s.Quantity)}).
ToList
For Each item In group
Debug.WriteLine(item.groupItem & ", " & item.groupCategory & ", " & item.sumQuantity)
Next
' A, CateA, 3 ' 期待通りの動作!
' B, CateB, 1
End Sub
Keyを付ける
匿名型にKeyをつけると期待通り。
Public Sub Hogehoge()
Dim details As New List(Of Items)
details.Add(New Items("A", "CateA", 1))
details.Add(New Items("A", "CateA", 2))
details.Add(New Items("B", "CateB", 1))
Dim group = details.GroupBy(Function(g) New With(Key g.Item, Key g.category)).
Select(Function(x) New With {.groupItem = x.Key.Item1, .groupCategory = x.Key.Item2, .sumQuantity = x.Sum(Function(s) s.Quantity)}).
ToList
For Each item In group
Debug.WriteLine(item.groupItem & ", " & item.groupCategory & ", " & item.sumQuantity)
Next
' A, CateA, 3 ' 期待通りの動作!
' B, CateB, 1
End Sub
感想
- 頑張ってC#から変換しても思うように行かなかった。
- 自分のような.Net初心者はC#とVBの匿名型の挙動が違うので知らないと積む。
- 他にやり方がありそう。