C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: List(Of Class)のループを使った要素の削除


(過去ログ 84 を表示中)

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■50011 / inTopicNo.1)  List(Of Class)のループを使った要素の削除
  
□投稿者/ パリス (1回)-(2010/05/26(Wed) 15:52:46)

分類:[VB.NET/VB2005 以降] 

こんにちは。
今、List(Of Class)を使用した処理を行っており、
1.List(Of Class)をループで回す。
2.要素であるClassのあるプロパティの条件により、この要素Classの内容で処理を行う。
3.この要素をListから削除する
ということをやりたいと考えています。
とりあえず、以下のソースのようにしてみましたが、
(ListTestは、List(Of Class)の変数です。)

For i = 0 To ListTest.Count - 1
    If (ListTest.Item(i)の内容が条件に合致する) Then
        '処理

        ListTest.RemoveAt(i)
    End If
Next

これだと、Removeが発生すると、Listの要素数が変わってしまい、インデックス範囲外の例外が発生してしまいます。
また、List要素の最後から処理を行えば、Removeの影響はなさそうですが、
ループを使用して行う処理の順番は、Listのインデックス順に行いたいのです。

どなたかお知恵を頂きたく、お願い致します。
開発言語はVB2008です。

引用返信 編集キー/
■50012 / inTopicNo.2)  Re[1]: List(Of Class)のループを使った要素の削除
□投稿者/ 魔界の仮面弁士 (1662回)-(2010/05/26(Wed) 16:02:07)
No50011 (パリス さん) に返信
> これだと、Removeが発生すると、Listの要素数が変わってしまい、インデックス範囲外の例外が発生してしまいます。

案1) ListTest.RemoveAll(Function(x) 削除条件式)
案2) ListTest.RemoveAll(AddressOf 削除条件メソッド)
案3) ListTest = (From q In ListTest Where Not 削除条件式).ToList()


> また、List要素の最後から処理を行えば、Removeの影響はなさそうですが、
> ループを使用して行う処理の順番は、Listのインデックス順に行いたいのです。

案4)

Dim index As Integer = 0
Do Until index >= ListTest.Count
 If [ListTest(index)を削除する条件] Then
  ListTest.RemoveAt(index)
 Else
  index += 1
 End If
Loop
引用返信 編集キー/
■50013 / inTopicNo.3)  Re[2]: List(Of Class)のループを使った要素の削除
□投稿者/ よねKEN (505回)-(2010/05/26(Wed) 16:24:44)
削除する直前に何か処理をしたいようなので、
私は案4がよいかなと思います。

No50012 (魔界の仮面弁士 さん) に返信
> 案4)
>
> Dim index As Integer = 0
> Do Until index >= ListTest.Count
>  If [ListTest(index)を削除する条件] Then
>   ListTest.RemoveAt(index)
>  Else
>   index += 1
>  End If
> Loop

ただ、以下のようにした方が条件が直感的ではないでしょうか。

Dim index As Integer = 0
While index < ListTest.Count
 If [ListTest(index)を削除する条件] Then
  ListTest.RemoveAt(index)
 Else
  index += 1
 End If
End While
引用返信 編集キー/
■50014 / inTopicNo.4)  Re[2]: List(Of Class)のループを使った要素の削除
□投稿者/ パリス (2回)-(2010/05/26(Wed) 16:30:19)
No50012 (魔界の仮面弁士 さん) に返信
> 案4) 

魔界の仮面弁士様、ご回答ありがとうございます。
今回は、処理対象の要素に対して処理が終わった後に削除するため、
以下のように案4を応用しようと思います。

Dim index As Integer = 0
Do Until index >= ListTest.Count
 If [ListTest(index)を処理する条件] Then
    '処理
  ListTest.RemoveAt(index)
 Else
  index += 1
 End If
Loop

魔界の仮面弁士様、ありがとうございました。

解決済み
引用返信 編集キー/
■50015 / inTopicNo.5)  Re[3]: List(Of Class)のループを使った要素の削除
□投稿者/ パリス (3回)-(2010/05/26(Wed) 17:10:05)
No50013 (よねKEN さん) に返信
> Dim index As Integer = 0
> While index < ListTest.Count
>  If [ListTest(index)を削除する条件] Then
>   ListTest.RemoveAt(index)
>  Else
>   index += 1
>  End If
> End While

あら、入れ違いでよねKEN様にもアドバイスを頂きました。
参考にさせていただきます。ありがとうございました。
解決済み
引用返信 編集キー/
■50018 / inTopicNo.6)  Re[4]: List(Of Class)のループを使った要素の削除
□投稿者/ 渋木宏明(ひどり) (1338回)-(2010/05/26(Wed) 17:53:48)
渋木宏明(ひどり) さんの Web サイト
インデックス値を自分で補正するのは、あとから見て「?」てなりそうな…

ToArray() とかで「列挙用」のコピーを作って、削除はオリジナルのコレクションに対して行うとか。
引用返信 編集キー/
■50027 / inTopicNo.7)  Re[5]: List(Of Class)のループを使った要素の削除
□投稿者/ よねKEN (506回)-(2010/05/26(Wed) 20:05:15)
2010/05/27(Thu) 14:02:16 編集(投稿者)
2010/05/26(Wed) 20:05:27 編集(投稿者)

> 2.要素であるClassのあるプロパティの条件により、この要素Classの内容で処理を行う。
> 3.この要素をListから削除する

この手順2、3が、1つの要素に対して連続で処理しなくてもよくて、
前から順番に処理したいのが手順2だけであれば、以下のように処理を2段階にする手もありますね。

' 削除対象インデックスの記録用
Dim removeIndexList As List(Of Integer) = New List(Of Integer)

For i = 0 To ListTest.Count - 1
    If (ListTest.Item(i)の内容が条件に合致する) Then
        '処理

        'ListTest.RemoveAt(i)
        removeIndexList.Add(i) ' 削除対象インデックスを記録
    End If
Next

' 削除は後ろから
For i = removeIndexList.Count - 1 To 0 Step -1
    ListTest.RemoveAt(removeIndexList(i))
Next

--
<修正>
No50059 のもりおさんのご指摘から、サンプルコードの不具合を修正。
(もりおさん、ご指摘ありがとうございます!)

■修正前
' 削除は後ろから
For i = removeIndexList.Count - 1 To 0 Step -1
    ListTest.RemoveAt(i)
Next
   ↓
■修正後
' 削除は後ろから
For i = removeIndexList.Count - 1 To 0 Step -1
    ListTest.RemoveAt(removeIndexList(i))
Next
</修正>

引用返信 編集キー/
■50059 / inTopicNo.8)  Re[6]: List(Of Class)のループを使った要素の削除
□投稿者/ もりお (226回)-(2010/05/27(Thu) 13:31:40)
No50027 (よねKEN さん) に返信

> ' 削除は後ろから
> For i = removeIndexList.Count - 1 To 0 Step -1
>     ListTest.RemoveAt(i)
> Next

釈迦に説法な予感ですが、
削除対象のインデックスは removeIndexList の要素に保持しているわけなので
removeIndexList から要素を取得して RemoveAt をした方が良いかと思います。

For i = removeIndexList.Count - 1 To 0 Step -1
    Dim removeIndex As Integer = removeIndexList(i)
    ListTest.RemoveAt(removeIndex)
Next

引用返信 編集キー/
■50063 / inTopicNo.9)  Re[7]: List(Of Class)のループを使った要素の削除
□投稿者/ よねKEN (509回)-(2010/05/27(Thu) 14:08:27)
No50059 (もりお さん) に返信
> ■No50027 (よねKEN さん) に返信
>
>>' 削除は後ろから
>>For i = removeIndexList.Count - 1 To 0 Step -1
>> ListTest.RemoveAt(i)
>>Next
>
> 釈迦に説法な予感ですが、
> 削除対象のインデックスは removeIndexList の要素に保持しているわけなので
> removeIndexList から要素を取得して RemoveAt をした方が良いかと思います。
>
> For i = removeIndexList.Count - 1 To 0 Step -1
> Dim removeIndex As Integer = removeIndexList(i)
> ListTest.RemoveAt(removeIndex)
> Next

ご指摘ありがとうございます。No50027 の投稿を修正してバグをなおしました。
引用返信 編集キー/
■50064 / inTopicNo.10)  Re[8]: List(Of Class)のループを使った要素の削除
□投稿者/ 渋木宏明(ひどり) (1339回)-(2010/05/27(Thu) 14:16:43)
渋木宏明(ひどり) さんの Web サイト
2010/05/27(Thu) 14:17:35 編集(投稿者)

>>釈迦に説法な予感ですが、
>>削除対象のインデックスは removeIndexList の要素に保持しているわけなので
>>removeIndexList から要素を取得して RemoveAt をした方が良いかと思います。
>>
>>For i = removeIndexList.Count - 1 To 0 Step -1
>> Dim removeIndex As Integer = removeIndexList(i)
>> ListTest.RemoveAt(removeIndex)
>>Next

1回でも ListTest.RemoveAt() すると、removeIndexList に格納されてるインデックス番号がズレません?

# あ、だから「後ろから」か (^^;
引用返信 編集キー/
■50065 / inTopicNo.11)  Re[9]: List(Of Class)のループを使った要素の削除
□投稿者/ れい (924回)-(2010/05/27(Thu) 14:28:32)
No50064 (渋木宏明(ひどり) さん) に返信
> # あ、だから「後ろから」か (^^;

後ろからだとリスト内の要素の移動量も少ないのでいいですよね。

そんな貧乏性な私は、
削除しないで新しいListに追加するという案をあげておきます。


For i = 0 To ListTest.Count - 1
If True Then
'処理
Else
NewListTest.Add(ListTest(i))
End If
Next
ListTest = NewListTest


引用返信 編集キー/
■50152 / inTopicNo.12)  Re[10]: List(Of Class)のループを使った要素の削除
□投稿者/ パリス (4回)-(2010/05/29(Sat) 09:12:32)
解決したつもりでいたので離れていましたが、みなさん、ご回答ありがとうございます。

No50065 (れい さん) に返信
> 削除しないで新しいListに追加するという案をあげておきます。

まさに目からウロコです。
この方法はインデックスを気にしなくていいので、とても分かりやすくていいです。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -