はじめに
これは、Visual Basic Advent Calendar 2024の14日目の記事となります。
11月13日に「.NET 9.0」 がリリースされました。
VB.NETは新機能の対応はしない方針ではあるが、記法に関係ない部分は対応します。
.NET 9.0でLINQに追加されたメソッド
.NET 9でLINQに追加された各メソッドCountBy
とAggregateBy
とIndex
ができるか確認してみました。
サンプルが分かりにくかったので下記サイトを参考に変更してみました。
共通モジュール
Public Class Person
Public FirstName As String
Public LastName As String
Public Point As Integer
End Class
Sub Main(args As String())
Dim people As New List(Of Person) From {
New Person With {.FirstName = "鈴木", .LastName = "一郎", .Point = 78},
New Person With {.FirstName = "鈴木", .LastName = "花子", .Point = 92},
New Person With {.FirstName = "山田", .LastName = "太郎", .Point = 85},
New Person With {.FirstName = "佐藤", .LastName = "健太", .Point = 95},
New Person With {.FirstName = "佐藤", .LastName = "美咲", .Point = 88}
}
CountBy
CountByメソッドは、グループ分けしてグループごとの個数を求めるメソッドです。
For Each sameFirstName In people.CountBy(Function(p) p.FirstName)
Console.WriteLine($"同じ苗字が {sameFirstName} 人、{sameFirstName}")
Next
結果
同じ苗字が 2 人、鈴木
同じ苗字が 1 人、山田
同じ苗字が 2 人、佐藤
AggregateBy
AggregateByはGroupByとAggregateを合体させたようなメソッドです。グルーピングしつつ、グループごとにアグリゲーション(まとめる、集計)メソッドです。
Dim aggregateBy = people.AggregateBy(Function(p) p.Point \ 10, Function(x) 0, Function(x, y) x + y.Point)
For Each kvp In aggregateBy
Console.WriteLine($"同一ポイント {kvp.Key * 10}点台 の集計結果 {kvp.Value}")
Next
結果
同一ポイント 70点台 の集計結果 78
同一ポイント 90点台 の集計結果 187
同一ポイント 80点台 の集計結果 173
Index
Indexメソッドは各要素をインデックスと合わせてタプルにした返すメソッドです。
For Each p In people.Index()
Console.WriteLine($"エントリー {p.Index + 1}: : Person {{ FirstName = {p.Item.FirstName}, LastName = {p.Item.LastName}, Point = {p.Item.Point} }}")
Next
Selectのオーバーロードを利用して同じことができる。
For Each item In people.Select(Function(Value, Index) New With {Value, Index})
Console.WriteLine($"エントリー {item.Index + 1}: Person {{ FirstName = {item.Value.FirstName}, LastName = {item.Value.LastName}, Point = {item.Value.Point} }}")
Next
結果
エントリー 1: Person { FirstName = 鈴木, LastName = 一郎, Point = 78 }
エントリー 2: Person { FirstName = 鈴木, LastName = 花子, Point = 92 }
エントリー 3: Person { FirstName = 山田, LastName = 太郎, Point = 85 }
エントリー 4: Person { FirstName = 佐藤, LastName = 健太, Point = 95 }
エントリー 5: Person { FirstName = 佐藤, LastName = 美咲, Point = 88 }
その他
LINQ以外でもOrderedDictionary
が追加されています。
OrderedDictionary
OrderedDictionaryクラスは順序を保証します。
Swift版のDictionary
クラスのように直ぐ順序に変更されるなら分かるのですが…
.NET版の通常のDictionary
クラスは順序を保証しない実装ですが、結構一致します。
' インスタンス作成
Dim dict As New OrderedDictionary(Of String, Integer) From {
{"A", 1},
{"B", 2},
{"C", 3}
}
' キーと要素を追加
dict.Add("D", 4)
' キーに紐づく要素を削除
dict.Remove("D")
' キーと要素を追加
dict.Add("E", 5)
' キーに紐づく要素を検索し、見つかった場合には要素を取得する
Dim value As Integer
If dict.TryGetValue("A", value) Then
Console.WriteLine(value) ' 1
End If
' 保持しているキーと要素を列挙する
' 追加した順番(登録した順番)で列挙する
For Each pair In dict
Console.WriteLine($"key = {pair.Key}, Value = {pair.Value}")
Next
結果
1
key = A, Value = 1
key = B, Value = 2
key = C, Value = 3
key = E, Value = 5
最後に
C# で作成して、ChatGPTでVB.NET に変換してみたんですが、まだちゃんとした対応されていないようで変な変換をしてしまう。
よって、ちゃんと理解した上で記事を修正しました。