反復内から要素を削除するとします。
a = ['a','b','c','d','e'];
for i = 0 to len(a){
print a[i];
if (i==1) a.remove(i);
};
出力はa b d e
、c
欠落ありです。これは、ループ中に配列を変更したために発生する一般的なバグです。いくつかの回避策には、ループ後に削除する要素のリストを保持し、削除後にインデックスを更新することが含まれます。この問題にどう対処しますか?
最も明白なアプローチは、配列の最後から最初まで反復することです。
a = ['a','b','c','d','e'];
for i = len(a)-1 downto 0 {
print a[i];
if (i==1) a.remove(i);
};
多くの言語には、反復子に削除を指示することにより、前方反復中に要素を削除することをサポートする反復子があります。ただし、これが常に機能するとは限りません (たとえば、Java によって返されるリストのイテレータはArrays.asList
要素の削除をサポートしません。リストはバッキング配列を「所有」していないためです。
インデックスを使用して前方反復する必要がある場合は、要素を削除するときに少なくともインデックスから 1 を減算します。そうすれば、要素をスキップしません。
それは、あなたのイテレータアクセス - あなたの例では位置5が最後まで存在しなくなったとしても、0から5まで繰り返すループを含む - がコレクション内の具体的な位置によるものなのか、それとも抽象参照によるものなのかによって異なります次の要素。
たとえば、Java の反復子は抽象型であるため、ポイント先の項目を削除してから、残りの項目を確実に反復処理を続けることができます。
C のような言語では、配列を繰り返し処理するときに、前述のような問題に直面することが多く、バグのあるコードを作成するリスクが高くなります。おそらく、最善の一般的な解決策は、削除したい「削除する」もののセットを蓄積し、それらを別のステップとして処理することです。コレクションの内部表現と反復の仕組みについて完全な知識がある場合にのみ、削除を安全に実行し、反復子 (およびループの終了条件) を正しく調整して反復を続行できます。ただし、配列を操作している場合は、とにかくケースによってこれが発生します。追加の調整コードが「削除する」セットを維持するためのコードよりも簡単かどうかの問題です。
イテレータを介してイテレーション内でも削除できます。
vector::iterator itVec = vectInt.begin();
for ( ; itVec != vectInt.end(); )
{
if (*itVec == 1022)
itVec = vectInt.erase(itVect);
else
++itVec;
}
(末尾の長さを記録する代わりに) 要素の末尾を認識し、メモリを解放するインタレータ応答。