SSブログ

VB.NET でArray.FindIndexを使ったユーザ定義型配列の検索方法 [プログラミング]

単純な配列から指定した文字列をもつ要素のインデックスを検索する場合、"Array.FindIndex"を使って検索する方法がある。

方法は二通りあって、一つは検索条件を記述したメソッドを呼び出す方法で、もう一つはラムダ式を記述する方法だ。

 

メソッドを呼び出す方法はこんな感じ…

 

--------------------------------------------------------------------------------------------------------------

    Private Function fncFindValue(ByVal pValue As String) As Boolean
        '*************************************
        '配列より特定の値をもつ要素を判定
        '
        '   pValue              :   配列の要素
        '
        '*************************************

        Dim blnReturn As Boolean

        '要素の値が指定値と一致するかを調べる
        If pValue = "acdb" Then
           blnReturn = True
        Else
           blnReturn = False
        End If
       
        Return blnReturn

    End Function


    Public Sub subFindArray
        '*************************************
        '配列より指定値と一致する要素のインデックスを取得
        '*************************************

        '配列を定義
        Dim strArray() As String = {"abcd", "acdb", "adbc"}

        '配列より指定値と一致する要素のインデクスを取得
        Dim intIndex As Integer = Array.FindIndex(strArray, AddressOf fncFindValue)

        MsgBox("'acdb'の値を持つ要素のインデックスは" & intIndex & "番目です。", MsgBoxStyle.Information)

    End Sub

--------------------------------------------------------------------------------------------------------------

 

しかし、この方法だと検索できる値は"acdb"に限られてしまうので、"fncFindValue"で調べる値を指定するためには

"acbd"の代わりにグローバル変数を使うしかない。

但し、グローバル変数を使った場合は、プログラムがマルチスレッドだと"subFindArray"が複数のスレッドから呼び出されると

正しい答えが得られない可能性がある。

 

そんな場合はラムダ式を使うと回避できる。こんな感じ…

 

--------------------------------------------------------------------------------------------------------------


    Public Sub subFindArray(ByVal pFindValue As String)
        '*************************************
        '配列より指定値と一致する要素のインデックスを取得
        '
        '   pFindValue          :   検索する値
        '
        '*************************************

        '配列を定義
        Dim strArray() As String = {"abcd", "acdb", "adbc"}
        '配列より指定値と一致する要素のインデクスを取得
        Dim intIndex As Integer = Array.FindIndex(strArray, Function(pArray As String)) _
                                                                pArray = pFindValue)

        MsgBox("'" & pFindValue & "'の値を持つ要素のインデックスは" & intIndex & "番目です。", _
               MsgBoxStyle.Information)

    End Sub


--------------------------------------------------------------------------------------------------------------
 

つまり、呼び出すFunctionを直接記述してしまう感じなので、"subFindArray"の引数"pFindValue"は呼び出すスレッドが

指定した値だから他のスレッドの影響を受けることはない。

 

さて、ここまではFindIndexを使用した単純な配列の検索方法で、本題はここから…

自分はユーザ定義型を配列にして利用することが良くあるが、その配列から特定の値を持つ要素を検索するとなると

For ... Next を使った検索方法が最初に思い浮かぶが、ちょっとスマートじゃないし 、もっと簡単に検索したい。

そこでArray.FindIndexを利用しようと思ってヘルプやネットを検索しても前述のような単純な配列の例題しか

見つけることができなかった。

なので、ユーザ定義型配列の検索方法を残しておこうと思う…。

 

先ほどと同様にメソッドを呼び出す方法はこんな感じ…

 

--------------------------------------------------------------------------------------------------------------

    'ユーザ定義型宣言
    Public Structure USER_TYPE
        Dim strValue As String
        Dim intNo As Integer
    End Structure

    Private Function fncFindValue(ByVal pArray As USER_TYPE) As Boolean
        '*************************************
        '配列より特定の値をもつ要素を判定
        '
        '   pArray              :   配列の要素
        '
        '*************************************

        Dim blnReturn As Boolean

        '要素の値が指定値と一致するかを調べる
        If pArray.strValue = "abcd" AndAlso pArray.intNo = 10 Then
           blnReturn = True
        Else
           blnReturn = False
        End If
       
        Return blnReturn

    End Function

    Public Sub subFindArray(ByVal pFindValue As String, ByVal As pFindNo as Integer)
        '*************************************
        '配列より指定値と一致する要素のインデックスを取得
        '
        '   pFindValue          :   検索する文字列値
        '   pNo                 :   検索する数値
        '
        '*************************************

        'ユーザ定義型の配列を定義
        Dim udtArray(2) As USER_TYPE

        '配列に値を設定
        For i As Integer = 0 To typArray.Length - 1
            udtArray(i) = New USER_TYPE
            With udtArray(i)
                .strValue = "abcd"
                .intNo = i * 10
            End With
        Next i
       
        '配列より指定値と一致する要素のインデクスを取得
        Dim intIndex As Integer = Array.FindIndex(udtArray, AddressOf fncFindValue)

        MsgBox("文字列'abcd'と数値'10'の値を持つ要素のインデックスは" & _
               intIndex & "番目です。", MsgBoxStyle.Information)

    End Sub

--------------------------------------------------------------------------------------------------------------

 

書いてみると「ごもっとも」って感じだが、ネット検索して例題を見つけたいときは動作が保証されたロジックが欲しいものだ。

単純な配列の時と異なるのは"fncFindValue"の中身。

この例ではメンバー"strValue"と"intNo"が共に一致する要素を判定している。

メンバーがもっと多数あってもっと複雑な条件でも応用できる。

 

さて、これをラムダ式で記述するとこんな感じになる。

 

--------------------------------------------------------------------------------------------------------------

    'ユーザ定義型宣言
    Public Structure USER_TYPE
        Dim strValue As String
        Dim intNo As Integer
    End Structure

    Public Sub subFindArray(ByVal pFindValue As String, ByVal As pFindNo as Integer)
        '*************************************
        '配列より指定値と一致する要素のインデックスを取得
        '
        '   pFindValue          :   検索する文字列値
        '   pNo                 :   検索する数値
        '
        '*************************************

        'ユーザ定義型の配列を定義
        Dim udtArray(2) As USER_TYPE

        '配列に値を設定
        For i As Integer = 0 To udtArray.Length - 1
            udtArray(i) = New USER_TYPE
            With udtArray(i)
                .strValue = "abcd"
                .intNo = i * 10
            End With
        Next i
       
        '配列より指定値と一致する要素のインデクスを取得
        Dim intIndex As Integer = Array.FindIndex(udtArray, Function(pArray As USER_TYPE)) _
                                                                pArray.strValue = pFindValue AndAlso _
                                                                pArray.intNo = pFindNo)

        MsgBox("文字列'" & pFindValue & "'と数値'" & pFindNo & "'の値を持つ要素のインデックスは" & _
               intIndex & "番目です。", MsgBoxStyle.Information)

    End Sub

--------------------------------------------------------------------------------------------------------------

これもまた書いてみると「ごもっとも」だ。

ということで、この例題が誰かの役に立ってくれるとありがたいと思う。

ページ幅の関係等で読みづらくても許してください…。

 


タグ:VB.NET
nice!(0)  コメント(0)  トラックバック(0) 

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 0

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。