忍者ブログ

VB.NET-TIPS などプログラミングについて

VB.NETのTIPS(小技集)を中心に、Javascript、PHP その他のプログラミングについて少し役に立つ情報を発信します。いわゆる個人的な忘備録ですが、みなさんのお役に立てれば幸いです。

コレクション「List」の使い方について

コレクションクラスの中に List がありますが、以前の記事の配列と似た処理が可能です。 配列では少し面倒だった領域を拡張などが無くなる分、使い勝手は良い様に思います。
それでは List の使い方について順を追って説明したいと思います。


■簡単な List の宣言と使い方

以下のソースを見て下さい。
処理の前半は、以前の配列を利用した場合の合計処理を示しています。 配列の各要素に値を設定する部分は、ベタに記述していますが、 合計を求めるところで指標を使ったループ処理で行っています。
処理の後半で List を生成し Add メソッドで新しく要素を追加します。 合計を求める処理では配列の様に Item プロパティで要素を取得しています。
尚、 List の要素を指標で取得する場合は、指標は「0」番目から始まります。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        '=== 配列宣言 ===
        Dim arr(5) As Integer
        '要素に値設定
        arr(1) = 1
        arr(2) = 10
        arr(3) = 100
        arr(4) = 1000
        arr(5) = 10000
        '指標宣言
        Dim i As Integer
        '合計計算
        Dim nSum As Integer = 0
        For i = 1 To 5
            nSum = nSum + arr(i)
        Next
        Console.WriteLine("配列を利用した場合の合計処理:{0}", nSum)

        '=== Listの生成 ===
        Dim list As New List(Of Integer)
        '要素に値を追加
        list.Add(1)
        list.Add(10)
        list.Add(100)
        list.Add(1000)
        list.Add(10000)
        nSum = 0
        '合計計算
        For i = 0 To list.Count - 1
            Console.WriteLine("{0}番目のListの要素:{1}", i, list.Item(i))
            nSum = nSum + list.Item(i)
        Next
        Console.WriteLine("List を利用した場合の合計処理:{0}", nSum)
    End Sub

実行結果がコンソールには以下様に表示されます。

配列を利用した場合の合計処理:11111
0番目のListの要素:1
1番目のListの要素:10
2番目のListの要素:100
3番目のListの要素:1000
4番目のListの要素:10000
List を利用した場合の合計処理:11111


List の繰り返し処理は For Each で行う

上記のソースでは List の要素を Item プロパティで取得しましたが、 For Each 文を使えば List の要素を順次取得できます。 (こちらの方が通常よく使います。)
そこで上記のソースを以下の様に変更し実行してみます。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        '=== Listの生成 ===
        Dim list As New List(Of Integer)
        '要素に値を追加
        list.Add(1)
        list.Add(10)
        list.Add(100)
        list.Add(1000)
        list.Add(10000)
        Dim nSum As Integer = 0
        '合計計算
        For Each nVal As Integer In list
            nSum = nSum + nVal
        Next
        Console.WriteLine("List を利用した場合の合計処理:{0}", nSum)
    End Sub

結果は最初の場合と同様になります。

List を利用した場合の合計処理:11111



List の初期化

List の生成とで一緒に初期化ができます。 生成の宣言の後に、From で繋ぎ {}(中括弧) で要素を ,(カンマ) で区切って記述します。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        ' Listの生成(初期化)
        Dim list As New List(Of Integer) From {1, 10, 100, 1000, 10000}
        '指標宣言
        Dim i As Integer = 0
        '合計計算
        Dim nSum As Integer = 0
        '合計計算
        For Each nVal As Integer In list
            Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal)
            i += 1              '指標+1
            nSum = nSum + nVal
        Next
        Console.WriteLine("List を利用した場合の合計処理:{0}", nSum)
    End Sub

実行結果は以下の通りで、データの順番は記述した順となっています。

0番目に取得したListの要素:1
1番目に取得したListの要素:10
2番目に取得したListの要素:100
3番目に取得したListの要素:1000
4番目に取得したListの要素:10000
List を利用した場合の合計処理:11111


このソース合計計算の For ループで「5」を直値(リテラル)で記述しています。 この場合は「5」であることが明らかなので問題は無いのですが、 配列の最終の指標が何か分からない時には UBound 等を用います。 以下に項目を新しくして説明します。

List の定義と各メソッド等について

List クラスは以下の様に定義されています。

Public Class List(Of T)
型パラメーター:
 T:リスト内の要素の型。
概要:
 インデックスを使用してアクセスできる、厳密に型指定されたオブジェクトのリストを表します。
 リストの検索、並べ替え、および操作のためのメソッドを提供します。

「リスト内の要素の型」にはいろんなものが設定可能で、データ型、オブジェクト型、コントロールオブジェクト等が指定できます。 また List クラスには以下の様なメソッドがあり、要素に対する各種の処理が可能です。

メソッド or
プロパティ
書式説明
Add Add(item As T)
 item:List(Of T) の末尾に追加するオブジェクト
List(Of T) の末尾にオブジェクトを追加します
AddRange AddRange(collection As IEnumerable(Of T))
 collection:List(Of T) の末尾に要素が追加されるコレクション
指定したコレクションの要素を List(Of T) の末尾に追加します
Clear Clear() 指定List(Of T) からすべての要素を削除します
Count Count As Integer  (これはプロパティ) List(Of T) に実際に格納されている要素の数を取得します
IndexOf IndexOf(item As T) As Integer  (プロパティ)
 item:List(Of T) 内で検索するオブジェクト
List(Of T) 全体内で item が見つかった場合は、
最初に見つかった位置の 0 から始まるインデックス
それ以外の場合は –1
IndexOf IndexOf(item As T, index As Integer) As Integer
 (プロパティ)
 item:List(Of T) 内で検索するオブジェクト
 index:検索の開始位置で 0 から始まるインデックス
List(Of T) 全体内で item が見つかった場合は、
最初に見つかった位置の 0 から始まるインデックス
それ以外の場合は –1
Insert Insert(index As Integer, item As T)
 index:挿入する位置の 0 から始まるインデックス
 item:挿入するオブジェクト
List(Of T) 内の指定したインデックスの位置に要素を挿入
Item Item(index As Integer) As T  (プロパティ)
 index:取得,設定する要素の 0 から始まるインデックス
 例外:ArgumentOutOfRangeException
 index が 0 未満,または List(Of T).Count 以上
指定したインデックスにある要素
Remove Remove(item As T) As Boolean
 item:List(Of T) から削除するオブジェクト
戻り値:
 item が正常に削除された場合は true,それ以外は false
List(Of T) 内で最初に見つかった特定のオブジェクトを削除します
RemoveAt RemoveAt(index As Integer)
 index:削除する要素の、0 から始まるインデックス
 例外:ArgumentOutOfRangeException
 index が 0 未満,または List(Of T).Count 以上
List(Of T) の指定したインデックスにある要素を削除します
RemoveRange RemoveRange(index As Integer, count As Integer)
 index:削除する要素の範囲の開始位置
  ( 0 から始まるインデックス)
 count:削除する要素の数
 例外:ArgumentOutOfRangeException
  index が 0 未満 または count が 0 未満
 例外:ArgumentException
  index, count が List(Of T) 内の要素の有効範囲外
List(Of T) から要素の範囲を削除します


上記のメソッド等を順を追って説明します。


AddRange コレクションの要素を末尾に追加

2個の List を生成し、最初の List に2番目の List を追加します。 この時 (Of T) のデータ型が同じで無い場合はエラーが発生します。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        '指標宣言
        Dim i As Integer = 0

        ' Listの生成(初期化)
        Dim list As New List(Of Integer) From {1, 10, 100, 1000, 10000}
        Dim listAdd As New List(Of Integer) From {2, 20, 200}

        ' AddRange 
        Console.WriteLine("=== AddRange ===")
        list.AddRange(listAdd)
        For Each nVal As Integer In list
            Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal)
            i += 1              '指標+1
        Next

        ' 異なる型のList
        Dim listAdd2 As New List(Of Long) From {3, 30, 300}
        Try
            ' エラーが必ず発生
            list.AddRange(listAdd2)
        Catch ex As Exception
            Console.WriteLine("AddRangeエラー:{0}", ex.Message)
        End Try
    End Sub

実行結果は以下の通りです。最初の AddRangeList の末尾に追加されたことが分かります。 また、異なるデータ型の場合にはエラーが発生しています。

=== AddRange ===
0番目に取得したListの要素:1
1番目に取得したListの要素:10
2番目に取得したListの要素:100
3番目に取得したListの要素:1000
4番目に取得したListの要素:10000
5番目に取得したListの要素:2
6番目に取得したListの要素:20
7番目に取得したListの要素:200
AddRangeエラー:型 'System.Collections.Generic.List`1[System.Int64]' のオブジェクトを型 'System.Collections.Generic.IEnumerable`1[System.Int32]' にキャストできません。


ClearCount について

先ず List を生成しその一覧を Item プロパティで取得し、その後 ClearList の要素を全て削除します。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        '指標宣言
        Dim i As Integer = 0
        ' Listの生成(初期化)
        Dim list As New List(Of Integer) From {1, 10, 100}
        ' Listの一覧
        Console.WriteLine("=== Listの一覧 ===")
        For i = 0 To list.Count - 1
            Console.WriteLine("{0}番目のListの要素:{1}", i, list.Item(i))
        Next

        Console.WriteLine("=== Clear ===")
        ' Clear
        list.Clear()
        Console.WriteLine("Listの要素個数:{0}", list.Count)
        i = 0
        For Each nVal As Integer In list    ' ForEachでの一覧は処理されない
            Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal)
            i += 1              '指標+1
        Next
    End Sub

実行結果は以下の通りです。CountList の件数分の一覧処理が行われることが分かります。 また Clear 後は件数が「0」になり For Each での処理が行われません。

=== Listの一覧 ===
0番目のListの要素:1
1番目のListの要素:10
2番目のListの要素:100
=== Clear ===
Listの要素個数:0


IndexOf コレクション要素のインデックスの検索

先ず List を生成しその要素の値指定でインデックスを IndexOf 関数で取得します。
その後、検索開始インデックスを指定する IndexOf での例を以下に示します。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        Dim i As Integer = 0

        ' Listの生成(初期化)                   0   1    2     3      4  5   6    7
        Dim list As New List(Of Integer) From {1, 10, 100, 1000, 10000, 2, 20, 200}

        ' IndexOf(item As T)
        Console.WriteLine("=== IndexOf(item As T) ===")
        i = list.IndexOf(1000)
        Console.WriteLine("itemが「{0}」のインデックス:{1}", 1000, i)
        i = list.IndexOf(1500)
        Console.WriteLine("itemが「{0}」のインデックス:{1}", 1500, i)

        ' IndexOf(item As T, index As Integer)
        Console.WriteLine("=== IndexOf(item As T, index As Integer) ===")
        i = list.IndexOf(20, 4)
        Console.WriteLine("itemが「{0}」をインデックス「{1}」から検索した結果のインデックス:{2}", 20, 4, i)
        i = list.IndexOf(1000, 4)
        Console.WriteLine("itemが「{0}」をインデックス「{1}」から検索した結果のインデックス:{2}", 1000, 4, i)
    End Sub

実行結果は以下の通りです。
要素の値指定のみの IndexOf では先頭から検索する為「1000」の値の場合はインデックス「3」が返り、 「1500」の値の場合は List の要素に存在しないので「-1」が返ります。
検索開始インデックスを指定する IndexOf では開始インデックスを「4」とし、検索要素値「20」の場合は「6」が返り、 検索要素値「1000」の場合はインデックスを「4」以降には値が存在しないので「-1」が返ります。

=== IndexOf(item As T) ===
itemが「1000」のインデックス:3
itemが「1500」のインデックス:-1
=== IndexOf(item As T, index As Integer) ===
itemが「20」をインデックス「4」から検索した結果のインデックス:6
itemが「1000」をインデックス「4」から検索した結果のインデックス:-1


Insert 指定したインデックスの位置に要素を挿入

先ず List を生成しインデックス「5」の位置に「300」を挿入します。
その後、存在しないインデックス「10」の位置に挿入処理を行いエラーが発生することを確認します。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        Dim i As Integer = 0

        ' Listの生成(初期化)
        Dim list As New List(Of Integer) From {1, 10, 100, 1000, 10000, 2, 20, 200}

        ' Insert(index As Integer, item As T)
        Console.WriteLine("=== Insert(index As Integer, item As T) ===")
        list.Insert(5, 300) 'インデックス「5」の位置に「300」を挿入
        i = 0
        For Each nVal As Integer In list
            Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal)
            i += 1              '指標+1
        Next
        Try
            ' エラーが必ず発生
            list.Insert(10, 900) 'インデックス「10」の位置に「900」を挿入
        Catch ex As Exception
            Console.WriteLine("Insertエラー:{0}", ex.Message)
        End Try
    End Sub

実行結果は以下の通りです。
インデックス「5」の位置に「300」が挿入され、それ以降は順次繰り下がったことがわかります。
また、インデックス「10」の位置での挿入処理はエラーが返されています。

=== Insert(index As Integer, item As T) ===
0番目に取得したListの要素:1
1番目に取得したListの要素:10
2番目に取得したListの要素:100
3番目に取得したListの要素:1000
4番目に取得したListの要素:10000
5番目に取得したListの要素:300
6番目に取得したListの要素:2
7番目に取得したListの要素:20
8番目に取得したListの要素:200
Insertエラー:インデックスは一覧の範囲内になければなりません。
パラメーター名:index


Remove RemoveAt RemoveRange 要素の削除

先ず List を生成し Remove で値が「300」の要素を削除します。2回行うことで異なる結果が返ってくるはずです。
その後 RemoveAt でインデックス「5」の位置を削除処理を行い一覧確認します。 さらに存在しないインデックス「10」の位置を削除処理し、エラー発生を確認します。
その後 RemoveRange でインデックス「3」の位置から「2」個の要素を削除処理を行い一覧確認します。 さらにインデックス「3」の位置から存在しない個数の「5」で削除処理し、エラー発生を確認します。

    Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click
        Dim i As Integer = 0

        ' Listの生成(初期化)
        Dim list As New List(Of Integer) From {1, 10, 100, 1000, 10000, 300, 2, 20, 200}

        Dim blnRet As Boolean
        ' Remove(item As T)
        Console.WriteLine("=== Remove(item As T) ===")
        blnRet = list.Remove(300)
        Console.WriteLine("itemが「{0}」削除:{1}", 300, blnRet)
        blnRet = list.Remove(300)
        Console.WriteLine("itemが「{0}」削除:{1}", 300, blnRet)

        ' RemoveAt(index As Integer)
        Console.WriteLine("=== RemoveAt(index As Integer) ===")
        list.RemoveAt(5)
        Console.WriteLine("インデックス「{0}」の要素を削除", 5)
        i = 0
        For Each nVal As Integer In list
            Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal)
            i += 1              '指標+1
        Next
        Try
            ' エラーが必ず発生
            list.RemoveAt(10) 'インデックス「10」の位置の要素削除
        Catch ex As Exception
            Console.WriteLine("RemoveAtエラー:{0}", ex.Message)
        End Try

        ' RemoveRange(index As Integer, count As Integer)
        Console.WriteLine("=== RemoveRange(index As Integer, count As Integer) ===")
        list.RemoveRange(3, 2)
        Console.WriteLine("インデックス「{0}」から「{1}」個の要素を削除", 3, 2)
        i = 0
        For Each nVal As Integer In list
            Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal)
            i += 1              '指標+1
        Next
        Try
            ' エラーが必ず発生
            list.RemoveRange(3, 5)
        Catch ex As Exception
            Console.WriteLine("RemoveRangeエラー:{0}", ex.Message)
        End Try
    End Sub

実行結果は以下の通りです。

=== Remove(item As T) ===
itemが「300」削除:True
itemが「300」削除:False
=== RemoveAt(index As Integer) ===
インデックス「5」の要素を削除
0番目に取得したListの要素:1
1番目に取得したListの要素:10
2番目に取得したListの要素:100
3番目に取得したListの要素:1000
4番目に取得したListの要素:10000
5番目に取得したListの要素:20
6番目に取得したListの要素:200
RemoveAtエラー:インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。
パラメーター名:index
=== RemoveRange(index As Integer, count As Integer) ===
インデックス「5」から「2」個の要素を削除
0番目に取得したListの要素:1
1番目に取得したListの要素:10
2番目に取得したListの要素:100
3番目に取得したListの要素:20
4番目に取得したListの要素:200
RemoveRangeエラー:配列のオフセットおよび長さが範囲を超えているか、カウンターがソース コレクションのインデックスから最後までの要素の数より大きい値です。

関連する記事

コレクション「List」と配列の相互変換について
コレクション「Dictionary」の使い方について
コレクション「Dictionary」から配列及び List への変換について
配列の使い方について(Dim, Redim)
配列の使い方の注意点について(コピー, Clone)
配列の範囲指定によるコピー(Array.Copy, Skip, Take)











PR

コメント

コメントを書く