現在ログインしていません。
新規アカウント作成
ログイン

Listや配列から重複を排除する

Distinctメソッドを使用するとList配列などから重複を排除できます。

1.単純な例

文字列のリストから重複を排除する例

Dim foods As New List(Of String)

foods.Add("りんご")
foods.Add("ぶどう")
foods.Add("メロン")
foods.Add("ぶどう"'←2個目のぶどう

'結果は りんご、ぶどう、メロン
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)

'結果は 1, 4, 7, 5 ,8, 6
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) = "ぶどう" '←2個目のぶどう

'結果は りんご、ぶどう、メロン
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)

'結果は 1, 4, 7, 5 ,8, 6
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)

'結果は 1, 4, 7, 5 ,8, 6
Dim uniqueNumbers = numbers.Distinct

MsgBox(String.Join(", ", uniqueNumbers))
■リスト5:型推論機能を使って戻り値の型の記述を省略する例

2.「重複」を独自に判定する例

ひらがなとカタカナの違いを重複とみなすか、大文字と小文字の違いは、メールアドレスが同じで、名前が違うユーザーを同一人物とするか、など重複の判断を独自に行いたい場合があります。 Distinctメソッドにはこのようなときのために、別途重複判断を行うクラスを定義して、そのクラスを使って重複判断をする機能があります。

次の例は ひらがな と カタカナ の違いだけの場合は重複とみなします。

Public Class Form1
    Private Sub Button1_Click(sender As Object, e As EventArgsHandles 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 StringAs 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 StringAs 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メソッドにはこのクラスのインスタンスを引数で指定します。

参考