[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
コレクションクラスの 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)
コメント