[2019/11/22] 文字列変換関数(StrConv)で変換が途中で切れる (No.141)
[2019/11/04] コレクション「List」の列挙中における要素の削除について (No.136)
[2019/10/28] コレクション「Dictionary」から配列及び List への変換について (No.134)
[2019/10/28] コレクション「Dictionary」の使い方について (No.133)
[2019/10/11] コレクション「List」と配列の相互変換について (No.131)
-
×
[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
-
文字列変換関数の StrConv を使っていて、変換結果が途中で切れてしまう現象が発生してしまいました。 普通に考えて以下の様な処理を行ったのですが、思った通りの結果が得られずに途中までしか変換されません。
文字列変換関数(StrConv)で変換が途中で切れるソース
Dim strOrg As String = "abcあいうえお" Dim str As String = StrConv(strOrg, VbStrConv.Wide) Debug.WriteLine("全角文字変換:" & str)
上記のソースの部分のみを実行させた場合に、デバッグ出力ウインドウに以下の様に表示されました。
全角文字変換:abcあ
予想変換結果は「abcあいうえお」のはずなのですが、上手く変換されません。 変換種類の第2引数を変えてもうまくいかない場合があります。
そこでネットで調べたのですが Visual Studio が互換モードで実行されていると、 この現象が発生することがわかりました。 早速、自分のPCの Visual Studio の実行ショートカットのプロパティを開いてみました。上図の様に互換性にチェックが入っていたので、互換性のチェックを外して以下の様にしました。
Visual Studio 再度起動しなおして、上記のソースを実行すると、当然のことながら以下の結果が表示されました。
全角文字変換:abcあいうえお
Visual Studio のインストールの時点で互換性をONしていたのかもしれません。今となってはよくわかりませんが。 StrConv の変換がなぜか上手くいかない場合は互換性をチェックしてみて下さい。関連する記事
⇒文字列定数(改行、タブ、バックスペース等)について
⇒文字列変換関数(StrConv)の使い方
PR -
コレクションクラスの List を For Each 等で要素の削除を行いたい場合があります。 List の要素の削除ぐらい簡単だと思っていたのですが、上手くいかなかった方法と、解決方法について記します。
- 簡単に考えていた List からの要素の削除(Remove)
- 解決方法その1・List を配列の様に扱い最後尾から削除(RemoveAt)
- 解決方法その2・ToArray メソッドと For Each による削除(Remove)
■簡単に考えていた List からの要素の削除(Remove)
List を For Each で要素を順次取得し、その要素値で削除してみました。
以下のソースを見て下さい。Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Listの生成(初期化) Dim list As New List(Of Integer) From {0, 1, 10, 100, 1, 1000, 1, 10000} ' 列挙中に削除する Console.WriteLine("=== Remove ===") For Each i As Integer In list Console.WriteLine("要素値「{0}」の表示", i) If i = 1 Then ' 要素値「1」が削除対象 Console.WriteLine("要素値「{0}」の削除", i) list.Remove(i) End If Next End Sub
実行結果がコンソールには以下様に表示されます。
2番目の要素「1」は削除されたのですが、その直後 Next のところで System.InvalidOperationException のエラーが発生してしまいます。 For Each で要素を順次取得中に List の内容を変更したため内部的に位置がずれ、エラーが発生した様です。=== Remove === 要素値「0」の表示 要素値「1」の表示 要素値「1」の削除
■解決方法その1・List を配列の様に扱い最後尾から削除(RemoveAt)
上記の方法では先頭から削除処理を行ったので内部的にずれが発生しエラーとなったので、 今度は最後尾から削除すれば行けるのではないかと以下のソースの様に変更しました。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Listの生成(初期化) Dim list As New List(Of Integer) From {0, 1, 10, 100, 1, 1000, 1, 10000} ' 列挙中に削除する Console.WriteLine("=== Remove ===") Dim nVal As Integer Dim i As Integer For i = list.Count - 1 To 0 Step -1 nVal = list.Item(i) Console.Write("{0}番目に取得したListの要素:{1}", i, nVal) If nVal = 1 Then '要素値「1」の削除(Index指定) list.RemoveAt(i) Console.Write("...削除", i) End If Console.WriteLine("") Next Console.WriteLine("=== 削除後 ===") i = 0 For Each nVal In list Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal) i += 1 Next End Sub
結果は以下の通りです。最後尾から順次、値が「1」のものが削除され、最後に一覧してみると値が「1」の要素は確かに削除されています。
=== Remove === 7番目に取得したListの要素:10000 6番目に取得したListの要素:1...削除 5番目に取得したListの要素:1000 4番目に取得したListの要素:1...削除 3番目に取得したListの要素:100 2番目に取得したListの要素:10 1番目に取得したListの要素:1...削除 0番目に取得したListの要素:0 === 削除後 === 0番目に取得したListの要素:0 1番目に取得したListの要素:10 2番目に取得したListの要素:100 3番目に取得したListの要素:1000 4番目に取得したListの要素:10000
■解決方法その2・ToArray メソッドと For Each による削除(Remove)
今度は For Each を使うのですが、最初の失敗した方法では無く List を ToArray メソッドにより配列として取得する方法を使います。 ToArray メソッドは List を別の配列として生成し、その配列から順次その要素を取得することになります。
直接 List にアクセスするのではなく、一旦別の配列にしてそれにアクセスするので当初の様にエラーが発生しません。Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Listの生成(初期化) Dim list As New List(Of Integer) From {0, 1, 10, 100, 1, 1000, 1, 10000} ' 列挙中に削除する Console.WriteLine("=== Remove ===") Dim nVal As Integer Dim i As Integer For Each nVal In list.ToArray Console.Write("{0}番目に取得したListの要素:{1}", i, nVal) If nVal = 1 Then '要素値「1」の削除 list.Remove(nVal) Console.Write("...削除", i) End If Console.WriteLine("") Next Console.WriteLine("=== 削除後 ===") i = 0 For Each nVal In list Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal) i += 1 Next End Sub
結果は以下の通りです。先頭から順次、値が「1」のものを削除します。 最後に一覧してみると値が「1」の要素は確かに削除されています。
=== Remove === 0番目に取得したListの要素:0 0番目に取得したListの要素:1...削除 0番目に取得したListの要素:10 0番目に取得したListの要素:100 0番目に取得したListの要素:1...削除 0番目に取得したListの要素:1000 0番目に取得したListの要素:1...削除 0番目に取得したListの要素:10000 === 削除後 === 0番目に取得したListの要素:0 1番目に取得したListの要素:10 2番目に取得したListの要素:100 3番目に取得したListの要素:1000 4番目に取得したListの要素:10000
関連する記事
⇒コレクション「List」の使い方について
⇒コレクション「List」と配列の相互変換について
⇒コレクション「Dictionary」の使い方について
⇒コレクション「Dictionary」から配列及び List への変換について
⇒配列の使い方について(Dim, Redim)
⇒配列の使い方の注意点について(コピー, Clone)
⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)
-
コレクションクラスの Dictionary は内部的にキー(Keys)と要素(Values)を別々のコレクションとして持っているので、 それぞれ個別に配列に変換ができます。
■Dictionary のキー・要素から配列及び List への変換(ToArray, ToList)
Dictionary のキー(Keys)及び要素(Values)はコレクションとして保持されていて、 そのコレクションとして以下の様なメソッドがあります。
メソッド or
プロパティ書式 説明 ToArray ToArray() As T()
戻り値:
コレクションの内容をそのデータ型の一次元配列を返すコレクションの内容を配列として返す ToList ToList() As List(Of T)
戻り値:
コレクションの内容を List コレクションとして返すコレクションの内容をList コレクションとして返す Count Count As Integer (これはプロパティ) コレクションに存在する要素の数を取得します CopyTo CopyTo(array() As T, index As Integer)
array:コレクションから要素がコピーされる 1次元の System.Array
index:コピーの開始位置で、array 内の 0 から始まるインデックス
例外:ArgumentOutOfRangeException
index が 0 未満
例外:ArgumentException
コレクションの要素数が index からコピー先の array の
末尾までに格納できる数を超えていますコレクション全体を互換性のある1次元の指定したインデックスから配列にコピーします
以下のソースを見て下さい。ToArray, ToList の例を記します。
配列からの要素取得は通常の For で直接要素を指標で指定し、 List の場合には For Each で順次要素を取得します。Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click Dim i As Integer = 0 ' Dictionaryの生成(初期化) Dim dic As New Dictionary(Of String, String) From _ {{"USA", "America"}, {"CHN", "China"}, {"JPN", "Japan"}} ' Values(要素の値)を配列へ変換 Dim arrVal() As String Console.WriteLine("=== Values : ToArray ===") arrVal = dic.Values.ToArray() For i = 0 To UBound(arrVal) Console.WriteLine("arrVal({0})の要素:{1}", i, arrVal(i)) Next ' Values(要素の値)を配列へのコピー Console.WriteLine("=== Values : ToList ===") Dim listV As List(Of String) = dic.Values.ToList i = 0 For Each Str As String In listV Console.WriteLine("{0}番目の要素:{1}", i, Str) i += 1 Next ' Keys(キーの値)を配列へ変換 Dim arrKey() As String Console.WriteLine("=== Keys : ToArray ===") arrKey = dic.Keys.ToArray For i = 0 To UBound(arrKey) Console.WriteLine("arrKey({0})の要素:{1}", i, arrKey(i)) Next ' Keys(キーの値)を配列へのコピー Console.WriteLine("=== Keys : ToList ===") Dim listK As List(Of String) = dic.Keys.ToList i = 0 For Each Str As String In listV Console.WriteLine("{0}番目の要素:{1}", i, Str) i += 1 Next End Sub
実行結果がコンソールには以下様に表示されます。
=== Values : ToArray === arrVal(0)の要素:America arrVal(1)の要素:China arrVal(2)の要素:Japan === Values : ToList === 0番目の要素:America 1番目の要素:China 2番目の要素:Japan === Keys : ToArray === arrKey(0)の要素:USA arrKey(1)の要素:CHN arrKey(2)の要素:JPN === Keys : ToList === 0番目の要素:USA 1番目の要素:CHN 2番目の要素:JPN
■Dictionary のメソッド CopyTo について
CopyTo メソッドは指定した配列のインデックスからコレクションをコピーします。
以下の例では、最初のディクショナリを ToArray により配列に変換後、2番目のディクショナリをその配列の直後にコピーしています。 コピーする前に配列の要素数を拡張しています。Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click Dim i As Integer = 0 ' Dictionaryの生成(初期化) Dim dic As New Dictionary(Of String, String) From _ {{"USA", "America"}, {"CHN", "China"}, {"JPN", "Japan"}} Dim dic2 As New Dictionary(Of String, String) From _ {{"FRA", "France"}, {"IRL", "Ireland"}, {"THA", "Thailand"}, {"BTN", "Bhutan"}} ' Values(要素の値)を配列へ変換 Dim arrVal() As String Console.WriteLine("=== Values : ToArray ===") arrVal = dic.Values.ToArray() For i = 0 To UBound(arrVal) Console.WriteLine("arrVal({0})の要素:{1}", i, arrVal(i)) Next ' Values(要素の値)を配列へのコピー Console.WriteLine("=== Values : CopyTo ===") Dim idxMax As Integer = UBound(arrVal) ReDim Preserve arrVal(idxMax + dic2.Values.Count) dic2.Values.CopyTo(arrVal, idxMax + 1) For i = 0 To UBound(arrVal) Console.WriteLine("arrVal({0})の要素:{1}", i, arrVal(i)) Next ' Keys(要素の値)を配列へ変換 Dim arrKey() As String Console.WriteLine("=== Keys : ToArray ===") arrKey = dic.Keys.ToArray For i = 0 To UBound(arrKey) Console.WriteLine("arrKey({0})の要素:{1}", i, arrKey(i)) Next ' Values(要素の値)を配列へのコピー Console.WriteLine("=== Keys : CopyTo ===") idxMax = UBound(arrKey) ReDim Preserve arrKey(idxMax + dic2.Keys.Count) dic2.Keys.CopyTo(arrKey, idxMax + 1) For i = 0 To UBound(arrKey) Console.WriteLine("arrKey({0})の要素:{1}", i, arrKey(i)) Next End Sub
結果は以下の通りです。
=== Values : ToArray === arrVal(0)の要素:America arrVal(1)の要素:China arrVal(2)の要素:Japan === Values : CopyTo === arrVal(0)の要素:America arrVal(1)の要素:China arrVal(2)の要素:Japan arrVal(3)の要素:France arrVal(4)の要素:Ireland arrVal(5)の要素:Thailand arrVal(6)の要素:Bhutan === Keys : ToArray === arrKey(0)の要素:USA arrKey(1)の要素:CHN arrKey(2)の要素:JPN === Keys : CopyTo === arrKey(0)の要素:USA arrKey(1)の要素:CHN arrKey(2)の要素:JPN arrKey(3)の要素:FRA arrKey(4)の要素:IRL arrKey(5)の要素:THA arrKey(6)の要素:BTN
関連する記事
⇒コレクション「List」の使い方について
⇒コレクション「List」と配列の相互変換について
⇒配列の使い方について(Dim, Redim)
⇒配列の使い方の注意点について(コピー, Clone)
⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)
-
コレクションクラスの中に Dictionary がありますが、以前の記事の List とは異なり、各要素にキー(索引)を持ちます。 そのキーを用いて要素にアクセスする連想配列の様なものです。 Dictionary クラスの定義は以下の様になっています。
■Dictionaryの宣言 Public Class Dictionary(Of TKey, TValue) 概要: キーと値のコレクションを表します。 型パラメーター: TKey : ディクショナリ内のキーの型。 TValue: ディクショナリ内の値の型。
それでは Dictionary の使い方について順を追って説明したいと思います。■簡単な Dictionary の宣言と使い方
以下のソースを見て下さい。
最初に Dictionary を生成し Add メソッドで新しく要素をキーと共に、3個追加します。 その後、追加したキーで要素を取得します。 尚、キーの指定で追加していないキーでの要素の取得を試みます。 (最後の取得でエラーが発生するはずです)Public Class frmDictionary Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Dictionaryの生成 Dim dic As New Dictionary(Of String, String) ' 要素の追加 dic.Add("A", "America") dic.Add("C", "China") dic.Add("J", "Japan") ' 要素の取得(KEY="A") Console.WriteLine("KEY:{0} のDictionaryの要素:{1}", "A", dic.Item("A")) ' 要素の取得(KEY="J") Console.WriteLine("KEY:{0} のDictionaryの要素:{1}", "J", dic.Item("J")) ' 要素に存在しないKEYの指定 Console.WriteLine("KEY:{0} のDictionaryの要素:{1}", "X", dic.Item("X")) End Sub End Class
実行結果としてコンソールには以下様に表示されますが、最後の取得で下図の様にエラーが発生します。
KEY:A のDictionaryの要素:America KEY:J のDictionaryの要素:Japan
■Dictionary の繰り返し処理は For Each で行う
上記のソースでは Dictionary の要素を Item プロパティで取得しましたが、 For Each 文を使えば Dictionary の要素を順次取得できます。 そこで上記のソースを以下の様に変更し実行してみます。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Dictionaryの生成 Dim dic As New Dictionary(Of String, String) ' 要素の追加 dic.Add("A", "America") dic.Add("C", "China") dic.Add("J", "Japan") ' For Each での順次処理 For Each item In dic ' 要素 Console.WriteLine("KEY:{0} のDictionaryの要素:{1}", item.Key, item.Value) Next End Sub
結果は以下の様になります。ここで For Each の item 変数なのですが、これは KeyValuePair 型になります。 これ自身は Structure なのでそのプロパティにアクセスしてキー(Key)と値(Value)を取得します。
KEY:A のDictionaryの要素:America KEY:C のDictionaryの要素:China KEY:J のDictionaryの要素:Japan
ここで KeyValuePair 型についてですが、VBでの内部では以下の様に宣言されています。
■KeyValuePairの宣言(一般的な宣言) Public Structure KeyValuePair(Of TKey, TValue)
この宣言は一般的なものであり、それぞれの Dictionary によって TKey、TValue の部分のデータ型が変わります。
■今回の例のKeyValuePairの宣言について Public Structure KeyValuePair(Of String, String)
依って、上記のソースの9行目は厳格に宣言するのであれば以下の様にします。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Dictionaryの生成 Dim dic As New Dictionary(Of String, String) ' 要素の追加 dic.Add("A", "America") dic.Add("C", "China") dic.Add("J", "Japan") ' For Each での順次処理 For Each item As KeyValuePair(Of String, String) In dic ' 要素 Console.WriteLine("KEY:{0} のDictionaryの要素:{1}", item.Key, item.Value) Next End Sub
尚 Dictionary にはキー及び値のみのコレクションを持っていますので、それぞれを別々に For Each 処理できます。Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Dictionaryの生成 Dim dic As New Dictionary(Of String, String) ' 要素の追加 dic.Add("A", "America") dic.Add("C", "China") dic.Add("J", "Japan") ' For Each でのキーの順次処理 For Each strKey As String In dic.Keys ' 要素 Console.WriteLine("KEY:{0}", strKey) Next ' For Each での値の順次処理 For Each strVal As String In dic.Values ' 要素 Console.WriteLine("Dictionaryの要素:{0}", strVal) Next End Sub
結果は以下の様になります。
KEY:A KEY:C KEY:J Dictionaryの要素:America Dictionaryの要素:China Dictionaryの要素:Japan
■Dictionary の初期化
Dictionary の生成とで一緒に初期化ができます。 生成の宣言の後に、From で繋ぎ {}(中括弧) で要素を ,(カンマ) で区切って記述します。 要素は { キー , 値 } の様に「キー」「値」をセットにします。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Dictionaryの生成 Dim dic As New Dictionary(Of String, String) From _ {{"A", "America"}, {"C", "China"}, {"J", "Japan"}} ' For Each での順次処理 For Each item In dic ' 要素 Console.WriteLine("KEY:{0} のDictionaryの要素:{1}", item.Key, item.Value) Next End Sub
実行結果は以下の通りです。
KEY:A のDictionaryの要素:America KEY:C のDictionaryの要素:China KEY:J のDictionaryの要素:Japan
■Dictionary の各メソッド・プロパティ等について
メソッド or
プロパティ書式 説明 Add Add(key As TKey, value As TValue)
key:追加する要素のキー
value:追加する要素の値(参照型の場合、null の値を使用可)指定したキーと値をディクショナリに追加します Clear Clear() Dictionary(Of TKey, TValue) から
すべてのキーと値を削除しますContainsKey ContainsKey(key As TKey) As Boolean
(プロパティ)
key:Dictionary(Of TKey, TValue) 内で検索されるキー
戻り値:
指定したキーを持つ要素が Dictionary(Of TKey, TValue) に
存在する場合は true,それ以外は false指定したキーが Dictionary(Of TKey, TValue)
での存在を確認しますCount Count As Integer (これはプロパティ) Dictionary(Of T) に存在する要素の数を取得します Item Item(key As TKey) As TValue (プロパティ)
key:取得または設定する値のキー
戻り値:
指定したキーに関連付けられている値
指定したキーが見つからなかった場合
get 操作は KeyNotFoundException をスロー
set 操作は指定したキーを持つ新しい要素を作成
例外:ArgumentNullException
index が 0 未満,または Dictionary(Of T).Count 以上
例外:KeyNotFoundException
プロパティが取得されたが,コレクション内に key が存在無し指定したキーに関連付けられている値を
取得または設定しますKeys Keys As Dictionary(Of TKey, TValue).KeyCollection
(プロパティ)
戻り値:
Dictionary(Of TKey, TValue) 内のキーを
格納しているDictionary(Of TKey, TValue).KeyCollectionDictionary(Of TKey, TValue) 内のキーを
格納しているコレクションを取得しますValues Values As Dictionary(Of TKey, TValue).ValueCollection
(プロパティ)
戻り値:
Dictionary(Of TKey, TValue) 内の値を
格納しているDictionary(Of TKey, TValue).KeyCollectionDictionary(Of TKey, TValue) 内の値を
格納しているコレクションを取得しますRemove Remove(key As TKey) As Boolean
key:削除する要素のキー
戻り値:
要素が見つかり、正常に削除された場合は true,
それ以外の場合は false
key が Dictionary(Of TKey, TValue) に存在しない場合,false指定したキーを持つ値を Dictionary(Of TKey, TValue) から削除します
上記のメソッド等を順を追って説明します。- Clear と ContainsKey と Count について
- IndexOf コレクション要素のインデックスの検索
- Insert 指定したインデックスの位置に要素を挿入
- Remove RemoveAt RemoveRange 要素の削除
■Clear と ContainsKey と Count について
先ず Dictionary を生成しDictionaryの件数を Count プロパティで取得し、その後 Clear で Dictionary の要素を全て削除します。 尚、 ContainsKey プロパティで Clear 前後でキーの存在確認を行います。
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click ' Dictionaryの生成 Dim dic As New Dictionary(Of String, String) From _ {{"A", "America"}, {"C", "China"}, {"J", "Japan"}} ' Dictionaryの件数 Console.WriteLine("Dictionaryの件数:{0}", dic.Count) ' ContainsKey確認 Dim key As String = "J" Console.WriteLine("キー[{0}]の存在確認:{1}", key, dic.ContainsKey(key)) ' Clear Console.WriteLine("=== Clear ===") dic.Clear() Console.WriteLine("Dictionaryの件数:{0}", dic.Count) ' ContainsKey確認 Console.WriteLine("キー[{0}]の存在確認:{1}", key, dic.ContainsKey(key)) End Sub
実行結果は以下の通りです。また Clear 後は件数が「0」になります。
Dictionaryの件数:3 キー[J]の存在確認:True === Clear === Dictionaryの件数:0 キー[J]の存在確認:False
■IndexOf コレクション要素のインデックスの検索
先ず Dictionary を生成しその要素の値指定でインデックスを IndexOf 関数で取得します。
その後、検索開始インデックスを指定する IndexOf での例を以下に示します。Private Sub btnDictionary_Click(sender As Object, e As EventArgs) Handles btnDictionary.Click Dim i As Integer = 0 ' Dictionaryの生成(初期化) 0 1 2 3 4 5 6 7 Dim list As New Dictionary(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」の値の場合は Dictionary の要素に存在しないので「-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 指定したインデックスの位置に要素を挿入
先ず Dictionary を生成しインデックス「5」の位置に「300」を挿入します。
その後、存在しないインデックス「10」の位置に挿入処理を行いエラーが発生することを確認します。Private Sub btnDictionary_Click(sender As Object, e As EventArgs) Handles btnDictionary.Click Dim i As Integer = 0 ' Dictionaryの生成(初期化) Dim list As New Dictionary(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}番目に取得したDictionaryの要素:{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番目に取得したDictionaryの要素:1 1番目に取得したDictionaryの要素:10 2番目に取得したDictionaryの要素:100 3番目に取得したDictionaryの要素:1000 4番目に取得したDictionaryの要素:10000 5番目に取得したDictionaryの要素:300 6番目に取得したDictionaryの要素:2 7番目に取得したDictionaryの要素:20 8番目に取得したDictionaryの要素:200 Insertエラー:インデックスは一覧の範囲内になければなりません。 パラメーター名:index
■Remove RemoveAt RemoveRange 要素の削除
先ず Dictionary を生成し Remove で値が「300」の要素を削除します。2回行うことで異なる結果が返ってくるはずです。 その後 RemoveAt でインデックス「5」の位置を削除処理を行い一覧確認します。 さらに存在しないインデックス「10」の位置を削除処理し、エラー発生を確認します。
その後 RemoveRange でインデックス「3」の位置から「2」個の要素を削除処理を行い一覧確認します。 さらにインデックス「3」の位置から存在しない個数の「5」で削除処理し、エラー発生を確認します。Private Sub btnDictionary_Click(sender As Object, e As EventArgs) Handles btnDictionary.Click Dim i As Integer = 0 ' Dictionaryの生成(初期化) Dim list As New Dictionary(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}番目に取得したDictionaryの要素:{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}番目に取得したDictionaryの要素:{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番目に取得したDictionaryの要素:1 1番目に取得したDictionaryの要素:10 2番目に取得したDictionaryの要素:100 3番目に取得したDictionaryの要素:1000 4番目に取得したDictionaryの要素:10000 5番目に取得したDictionaryの要素:20 6番目に取得したDictionaryの要素:200 RemoveAtエラー:インデックスが範囲を超えています。負でない値で、コレクションのサイズよりも小さくなければなりません。 パラメーター名:index === RemoveRange(index As Integer, count As Integer) === インデックス「5」から「2」個の要素を削除 0番目に取得したDictionaryの要素:1 1番目に取得したDictionaryの要素:10 2番目に取得したDictionaryの要素:100 3番目に取得したDictionaryの要素:20 4番目に取得したDictionaryの要素:200 RemoveRangeエラー:配列のオフセットおよび長さが範囲を超えているか、カウンターがソース コレクションのインデックスから最後までの要素の数より大きい値です。
関連する記事
⇒コレクション「List」の使い方について
⇒コレクション「List」と配列の相互変換について
⇒コレクション「Dictionary」から配列及び List への変換について
⇒配列の使い方について(Dim, Redim)
⇒配列の使い方の注意点について(コピー, Clone)
⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)
-
コレクションクラスの List と配列は相互に変換ができます。 「コレクション「List」の使い方について」の記事では配列との変換について記述していませんでしたので、ここでまとめます。
■List から配列への変換(ToArray, CopyTo)
変換を行う為に List の ToArray 関数及び CopyTo メソッドを使いますが、 それぞれの定義は以下の様になります。
メソッド
or 関数書式 説明 ToArray ToArray() As T()
戻り値:List(Of T) の要素のコピーを格納する配列List(Of T) の要素を新しい配列にコピーします CopyTo CopyTo(array() As T)
array:List(Of T) から要素がコピーされる 1次元の System.Array
System.Array には、0 から始まるインデックス番号が必要ですList(Of T) 全体を互換性のある1次元の先頭から配列にコピーします CopyTo CopyTo(array() As T, index As Integer)
array:List(Of T) から要素がコピーされる 1次元の System.Array
index:コピーの開始位置で、array 内の 0 から始まるインデックス
例外:ArgumentOutOfRangeException
index が 0 未満
例外:ArgumentException
List(Of T) の要素数が index からコピー先の array の
末尾までに格納できる数を超えていますList(Of T) 全体を互換性のある1次元の指定したインデックスから配列にコピーします
以下のソースを見て下さい。ToArray, CopyTo の例を記します。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 list2 As New List(Of Integer) From {2, 20, 200} ' 配列へ変換 Dim arr() As Integer Console.WriteLine("=== ToArray ===") arr = list.ToArray For i = 0 To UBound(arr) Console.WriteLine("arr({0})の要素:{1}", i, arr(i)) Next ' 配列へのコピー Console.WriteLine("=== CopyTo ===") list2.CopyTo(arr) For i = 0 To UBound(arr) Console.WriteLine("arr({0})の要素:{1}", i, arr(i)) Next ' 最初に少ないListデータを配列へ変換 arr = list2.ToArray Try ' エラーの起きる配列へのコピー list.CopyTo(arr) Catch ex As Exception Console.WriteLine("CopyToエラー:{0}", ex.Message) End Try ' 再度listから変換 arr = list.ToArray ' インデックスを指定して配列へのコピー Console.WriteLine("=== CopyTo(index) ===") list2.CopyTo(arr, 2) For i = 0 To UBound(arr) Console.WriteLine("arr({0})の要素:{1}", i, arr(i)) Next End Sub
実行結果がコンソールには以下様に表示されます。
10行目の ToArray 関数により「list」から「arr」に変換され、要素がコピーされていることが分かります。 17行目の CopyTo メソッドにより「list2」から「arr」の先頭から要素が上書きコピーされていることが分かります。 「arr」の要素(3),(4)はそのままになっています。
再度「list2」から「arr」に変換し、26行目で要素数の多い「list」を上書きコピーさせています。 「arr」は要素数が足りないので、エラーが発生します。
再度「list」から「arr」に変換し、35行目で2番目の要素から「list2」を上書きコピーさせています。=== ToArray === arr(0)の要素:1 arr(1)の要素:10 arr(2)の要素:100 arr(3)の要素:1000 arr(4)の要素:10000 === CopyTo === arr(0)の要素:2 arr(1)の要素:20 arr(2)の要素:200 arr(3)の要素:1000 arr(4)の要素:10000 CopyToエラー:ターゲット配列の長さが足りません。destIndex、長さ、および配列の最小値を確認してください。 === CopyTo(index) === arr(0)の要素:1 arr(1)の要素:10 arr(2)の要素:2 arr(3)の要素:20 arr(4)の要素:200
■List の生成(New)で配列指定
List を生成する時に配列を指定すれば、配列要素をコピーして生成されます。
New の引数として IEnumerator(Of T) が必要なのですが、配列(System.Array)はこれを持っているため、指定ができます。 尚、New の引数として List を用いても同様にできます。
AddRange でも同様に引数に配列を指定することができます。Private Sub btnList_Click(sender As Object, e As EventArgs) Handles btnList.Click Dim i As Integer = 0 ' 配列宣言・初期化 Dim arr() As Integer = {1, 20, 300} ' 配列を指定したListの生成 Console.WriteLine("=== New(配列) ===") Dim list As New List(Of Integer)(arr) i = 0 For Each nVal As Integer In list Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal) i += 1 Next ' Listを指定したList2の生成 Console.WriteLine("=== New(List) ===") Dim list2 As New List(Of Integer)(list) i = 0 For Each nVal As Integer In list2 Console.WriteLine("{0}番目に取得したList2の要素:{1}", i, nVal) i += 1 Next ' 配列をListに追加 Console.WriteLine("=== AddRange ===") list.AddRange(arr) i = 0 For Each nVal As Integer In list Console.WriteLine("{0}番目に取得したListの要素:{1}", i, nVal) i += 1 Next End Sub
結果は以下の通りです。
=== New(配列) === 0番目に取得したListの要素:1 1番目に取得したListの要素:20 2番目に取得したListの要素:300 === New(List) === 0番目に取得したList2の要素:1 1番目に取得したList2の要素:20 2番目に取得したList2の要素:300 === AddRange === 0番目に取得したListの要素:1 1番目に取得したListの要素:20 2番目に取得したListの要素:300 3番目に取得したListの要素:1 4番目に取得したListの要素:20 5番目に取得したListの要素:300
関連する記事
⇒コレクション「List」の使い方について
⇒配列の使い方について(Dim, Redim)
⇒配列の使い方の注意点について(コピー, Clone)
⇒配列の範囲指定によるコピー(Array.Copy, Skip, Take)