none
配列をどう適用していいのかわかりません RRS feed

  • 質問

  • VB2010を利用しています。 

    次のようなコードをシンプルにしたいと思っております。

           Dim check As String
            Dim checklist001 As New List(Of String)
            Dim checklist002 As New List(Of String)
            Dim checklist003 As New List(Of String)

            check = "check002"
            Select Case check

                Case "check001"
                    checklist001.Add("check001")

                Case "check002"
                    checklist002.Add("check002")

                Case "check003"
                    checklist003.Add("check003")

            End Select

    変数checkに代入された値に応じて、その値と同じ変数名を持つ、
    LIST型のchecklist001~checklist003 になにがしかの処理を
    行います。

    checkの値が上記のように3個であれば、select文を使う方法でも
    かまいませんが、checkの値が1000個ですと、select文を記述する
    ことは大変となってきます。

    checklist を配列、LIST、もしくは何らかの方法で定義し、

    理想: checklist(check).add(check)

    というようなスタイルで記述できれば短いコードですむと思うのですが、
    その方法がわかりません。

    うまい方法をご存じでしたらご教授願います。


    doratch

    2012年6月28日 8:18

回答

  • こんな感じかなぁ。

            Dim check As String = "check002"
            Dim checkList As New Dictionary(Of String, List(Of String))
    
            'リストにセット
            If Not checkList.ContainsKey(check) Then
                checkList.Add(check, New List(Of String))
            End If
            checkList(check).Add(check)
    
            'リストから抜き出し
            For Each pair As KeyValuePair(Of String, List(Of String)) In checkList
                Dim key As String = pair.Key
                Dim value As List(Of String) = pair.Value
            Next
    
            'リストから指定キーを抜き出し
            If checkList.ContainsKey(check) Then
                Return checkList(check)
            Else
                Return New List(Of String)
            End If

    • 編集済み aviator__ 2012年6月28日 8:43 指定キーを抜き出しを追記
    • 回答としてマーク doratch 2012年6月28日 9:52
    2012年6月28日 8:39

すべての返信

  • こんな感じかなぁ。

            Dim check As String = "check002"
            Dim checkList As New Dictionary(Of String, List(Of String))
    
            'リストにセット
            If Not checkList.ContainsKey(check) Then
                checkList.Add(check, New List(Of String))
            End If
            checkList(check).Add(check)
    
            'リストから抜き出し
            For Each pair As KeyValuePair(Of String, List(Of String)) In checkList
                Dim key As String = pair.Key
                Dim value As List(Of String) = pair.Value
            Next
    
            'リストから指定キーを抜き出し
            If checkList.ContainsKey(check) Then
                Return checkList(check)
            Else
                Return New List(Of String)
            End If

    • 編集済み aviator__ 2012年6月28日 8:43 指定キーを抜き出しを追記
    • 回答としてマーク doratch 2012年6月28日 9:52
    2012年6月28日 8:39
  • aviator様

    早速のご回答ありがとうございました。

    おかげさまで、教えていただいた方法で、期待しているものが実現できることがわかりました。

    ありがとうございました。


    doratch

    2012年6月28日 9:51
  • 解決されたみたいなのですが・・・
    やろうとされていることは他の場所でも使うでのはないかと思いますので、
    下記のように2つクラスを使ったほうがスマートかなと思います。

        Private Sub Exec()
            Dim CheckA As New Check(Of String)
            CheckA.Name = "Aのチェック"
            CheckA.TargetList.Add("aaa1")
            CheckA.TargetList.Add("aaa2")
    
            Dim CheckB As New Check(Of String)
            CheckB.Name = "Bのチェック"
            CheckB.TargetList.Add("bbb1")
            CheckB.TargetList.Add("bbb2")
            CheckB.TargetList.Add("bbb3")
    
            Dim MyCheck As New MyCheck(Of String)
            MyCheck.Checklist.Add(CheckA)
            MyCheck.Checklist.Add(CheckB)
    
            Dim SearchCheck As Check(Of String)
            SearchCheck = MyCheck.GetTargetList("Aのチェック")
            If SearchCheck IsNot Nothing Then
                SearchCheck.TargetList.Add("aaa3")
            End If
    
            '下記のようにもできますが、GetTargetListでNothingが帰ってくるとコケます
            MyCheck.GetTargetList("Aのチェック").TargetList.Add("aaa3")
    
        End Sub
    
        ''' <summary>
        ''' TargetListと名称のみもつクラス
        ''' </summary>
        Public Class Check(Of T)
            Private _Name As String = String.Empty
            Private _TargetList As New List(Of T)
    
            Public Property Name()
                Get
                    Return _Name
                End Get
                Set(ByVal value)
                    _Name = value
                End Set
            End Property
    
            Public Property TargetList() As List(Of T)
                Get
                    Return _TargetList
                End Get
                Set(ByVal value As List(Of T))
                    _TargetList = value
                End Set
            End Property
        End Class
    
        ''' <summary>
        ''' Checkクラスのリストと検索メソッドを持つクラス
        ''' </summary>
        Public Class MyCheck(Of T)
            Private _CheckList As New List(Of Check(Of T))
    
            Public Property Checklist() As List(Of Check(Of T))
                Get
                    Return _CheckList
                End Get
                Set(ByVal value As List(Of Check(Of T)))
                    _CheckList = value
                End Set
            End Property
    
            Public Function GetTargetList(ByVal _name As String) As Check(Of T)
                Return _CheckList.Find(Function(p) p.Name = _name)
            End Function
        End Class
    
    ジェネリッククラスとFindなどのメソッドはとても便利なのでちょっと時間を割いて習得されてはどうでしょうか。
    2012年6月29日 6:29
  • このケースでスマートさを求めるのであれば、クラス2つはどうかと思います。

    クラスは下記の1つで十分かと、

    Public Class ListWithKey(Of T)
        Private _list As New Dictionary(Of String, List(Of T))
    
        Public Function ListOf(ByVal key As String) As List(Of T)
            If Not _list.ContainsKey(key) Then
                _list.Add(key, New List(Of T))
            End If
            Return _list(key)
        End Function
    End Class
    

    これであれば、

            Dim keyList As New ListWithKey(Of String)
            keyList.ListOf("Aのチェック").Add("aaa1")
            keyList.ListOf("Aのチェック").Add("aaa2")
            keyList.ListOf("Aのチェック").Add("aaa3")
            keyList.ListOf("Bのチェック").Add("bbb1")
            keyList.ListOf("Bのチェック").Add("bbb2")
            keyList.ListOf("Cのチェック").Add("ccc1")
    
            Dim list As List(Of String) = keyList.ListOf("Aのチェック")
    

    みたいな形で未セットの時等も良い感じに使えるかと思います。※未セットのキーを取得しようとすると空のリストが取得される。

    あとこれは余談ですが、

    「MyCheck.GetTargetList("Aのチェック").TargetList.Add("aaa3")」

    みたいに、GetTargetList メソッドの返り値のメンバに TargetList がいるってのはソースの誤読に繋がるので避けるべきだと思います。

            Public Function GetTargetList(ByVal _name As String) As List(Of T)
                Return _CheckList.Find(Function(p) p.Name = _name).TargetList
            End Function
    

    の方が良いと思います。

    2012年6月29日 11:25