foreach ループで現在反復しているコレクションからアイテムを削除することを許可する必要がありますか?
もしそうなら、正しい行動は何ですか?
foreach ループで現在反復しているコレクションからアイテムを削除することを許可する必要がありますか?
もしそうなら、正しい行動は何ですか?
コレクションへの変更を追跡して位置情報を正確に保つ列挙子をサポートするために、非常に洗練された Collection を使用できます。たとえそれがあったとしても、ある程度の妥協や仮定を行う必要があります. そのため、ほとんどのライブラリは単にそのようなことを禁止したり、ドキュメントで予期しない動作についてつぶやいたりしています。
したがって、最も安全な方法はループすることです。削除が必要なものへの参照を収集し、その後、収集した参照を使用して元のコレクションからアイテムを削除します。
それは本当に言語に依存します。配列を変更すると、配列を叩いて爆発するものもあります。一部は配列を使用し、爆発しません。イテレータ (より堅牢) を呼び出して問題なく続行するものもあります。
通常、foreach
ループ内でコレクションを変更することはお勧めできません。これは、ユーザーの意図がプログラムに認識されないためです。変更前のすべてのアイテムをループするつもりだったのですか、それとも新しい構成に合わせたいだけですか? すでにループされたアイテムはどうですか?
代わりに、コレクションを変更する場合は、ループするアイテムの定義済みリストを作成するか、インデックス付きループを使用します。
ハッシュ テーブルや辞書などの一部のコレクションには「位置」の概念がなく、通常、反復の順序は保証されません。したがって、反復中にアイテムの削除を許可することは非常に困難です。
逆方向に繰り返し、アイテムを1つずつ削除します...これで適切な解決策になるはずです。
いいえ、すべきではありません。正しい動作は、潜在的な同時実行の問題が発生したことを通知することですが、それは選択した言語で行われます(例外をスローし、エラーコードを返し、シグナルをraise()します)。
要素を反復処理しているときにデータ構造を変更すると、イテレータが無効になる可能性があります。つまり、コレクションの一部ではなくなったオブジェクトで作業するリスクがあります。より複雑な表記法に基づいて要素をフィルタリングする場合は、次のようにすることができます(Javaの場合)。
List<T> toFilter = ...;
List<T> shadow;
for ( T element : toFilter )
if ( keep(element) )
shadow.add(element);
/* If you'll work with toFilter in the same context as the filter */
toFilter = shadow;
/* Alternatively, if you want to modify toFilter in place, for instance if it's
* been given as a method parameter
*/
toFilter.clear();
toFilter.addAll(shadow);
イテレータを明示的に使用するためにイテレートしているコレクションからアイテムを削除する最良の方法。例えば。
List<String> myList = ArrayList<String>();
Iterator<String> myIt = myList.iterator();
while (myIt.hasNext()) {
myIt.remove();
}
まず foreach の概念を理解する必要があり、実際にはプログラミング言語に依存します。しかし、一般的な答えとして、 foreach 内でコレクションを変更することは避けるべきです
標準の for ループを使用し、アイテム コレクションを逆方向に繰り返すだけで、問題なくアイテムを削除できます。