Listや配列から重複を排除する
Distinctメソッドを使用すると
Listや
配列などから重複を排除できます。
1.単純な例
文字列のリストから重複を排除する例
Dim foods As New List(Of String)
foods.Add("りんご")
foods.Add("ぶどう")
foods.Add("メロン")
foods.Add("ぶどう")
Dim uniqueFoods As List(Of String) = foods.Distinct.ToList
MsgBox(String.Join(", ", uniqueFoods))
■リスト1:数値のリストから重複を排除する例
Dim numbers As New List(Of Integer)
numbers.Add(1)
numbers.Add(4)
numbers.Add(7)
numbers.Add(5)
numbers.Add(8)
numbers.Add(4)
numbers.Add(6)
numbers.Add(5)
Dim uniqueNumbers As List(Of Integer) = numbers.Distinct.ToList
MsgBox(String.Join(", ", uniqueNumbers))
■リスト2:文字列の配列から重複を排除する例
対象が配列になっているだけでDistinctメソッドの使い方は同じです。
Dim foods(3) As String
foods(0) = "りんご"
foods(1) = "ぶどう"
foods(2) = "メロン"
foods(3) = "ぶどう"
Dim uniqueFoods() As String = foods.Distinct.ToArray
MsgBox(String.Join(", ", uniqueFoods))
■リスト3:補足
以上の例では、理解しやすさを優先して、ToListメソッドやToArrayメソッドを使って元の型と結果の型が同じになるようにしています。 これらは重複の排除には関係ありません。
Distinct自体の戻り値はIEnumerable(Of xxxx)として受け取ることができ、このままでもいろいろな操作ができます。 必要になった場合ToListを呼び出してList(Of xxxx)に変換したり、ToArrayを呼び出して配列に変換したりできます。
Dim numbers As New List(Of Integer)
numbers.Add(1)
numbers.Add(4)
numbers.Add(7)
numbers.Add(5)
numbers.Add(8)
numbers.Add(4)
numbers.Add(6)
numbers.Add(5)
Dim uniqueNumbers As IEnumerable(Of Integer) = numbers.Distinct
MsgBox(String.Join(", ", uniqueNumbers))
■リスト4:IEnumerable(Of Integer)として戻り値を受け取る例型推論機能を使えば戻り値の型を記述する必要すらありません。しかし、プログラムを一目見ても型がわかりにくいためコードの可読性は下がります。
Dim numbers As New List(Of Integer)
numbers.Add(1)
numbers.Add(4)
numbers.Add(7)
numbers.Add(5)
numbers.Add(8)
numbers.Add(4)
numbers.Add(6)
numbers.Add(5)
Dim uniqueNumbers = numbers.Distinct
MsgBox(String.Join(", ", uniqueNumbers))
■リスト5:型推論機能を使って戻り値の型の記述を省略する例2.「重複」を独自に判定する例
ひらがなとカタカナの違いを重複とみなすか、大文字と小文字の違いは、メールアドレスが同じで、名前が違うユーザーを同一人物とするか、など重複の判断を独自に行いたい場合があります。 Distinctメソッドにはこのようなときのために、別途重複判断を行うクラスを定義して、そのクラスを使って重複判断をする機能があります。
次の例は ひらがな と カタカナ の違いだけの場合は重複とみなします。
Public Class Form1
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim foods As New List(Of String)
foods.Add("りんご")
foods.Add("ぶどう")
foods.Add("リンゴ")
foods.Add("メロン")
Dim uniqueFoods As List(Of String) = foods.Distinct(New HiraganaKatakanaComparer).ToList
MsgBox(String.Join(", ", uniqueFoods))
End Sub
End Class
Public Class HiraganaKatakanaComparer
Implements IEqualityComparer(Of String)
Public Overloads Function Equals(x As String, y As String) As Boolean Implements IEqualityComparer(Of String).Equals
Dim xKatakana As String = StrConv(x, VbStrConv.Katakana)
Dim yKatakana As String = StrConv(y, VbStrConv.Katakana)
Return EqualityComparer(Of String).Default.Equals(xKatakana, yKatakana)
End Function
Public Overloads Function GetHashCode(obj As String) As Integer Implements IEqualityComparer(Of String).GetHashCode
Dim objKatakana As String = StrConv(obj, VbStrConv.Katakana)
Return objKatakana.GetHashCode
End Function
End Class
■リスト6:HiraganaKatakanaComparerが、独自に定義した重複を判断するクラスです。このクラスはIEqualityComparerインターフェースを実装することが必須です。
Equalsメソッドには引数で与えられる2つの値x, y を同じとみなすかどうか判断してTrue, Falseを返すロジックを書きます。
GetHashCodeメソッドには、値を一意に識別するための数値(このような数値をハッシュと呼びます。)を返すロジックを書きます。
Distinctメソッドにはこのクラスのインスタンスを引数で指定します。
参考