0

だから私は unsigned ints (vector<unsigned int>と呼ばれるvector1) のベクトルを持っています。作成した構造体の別のベクトルがあります (vector<struct>と呼ばれvector2ます)。vector<int>のインデックスである整数を保持しますvector<struct>。たとえば、としましょうvector<int = {5, 17, 18, 19}。つまりvector2.at(5) == vector2.at(vector1.at(0))

構造体には、と呼ばれるブール変数がありますvar。ほとんどの場合、varは false です。= trueのすべての要素vector1を削除したい。var

私がしたことは:

for (unsigned int i = 0; i < vector1.size(); i++)
{
   if (vector2.at(vector1.at(i)).var)
    vector1.erase(vector.begin() + i);
}

これに関する唯一の問題は、すべての真の要素が削除されないことです。すべての値を削除するために for ループを複数回実行しました。これは正しい動作ですか?そうでない場合、どこで間違ったのでしょうか?

4

3 に答える 3

3

ベクトルから要素を削除するには、 erase-remove イディオムを使用する必要があります。

v.erase(std::remove(v.begin(), v.end(), value), v.begin);

std::remove要素をベクトルの最後に移動し、要素をベクトルeraseから消去します。

于 2013-02-06T15:45:24.653 に答える
1

一時的なベクトルを保持し、ループ内vector1でそれをコピーして反復し、から削除できます。forvector1

于 2013-02-06T15:48:19.920 に答える
1

ベクター内の要素を消去しながら、同時にそれを反復しています。そのため、要素を消去するときは常に次の要素にジャンプします。これiは、ベクトルを短縮しただけで増加するためですi(インデックス ループの代わりに適切なイテレータ ループを使用していた場合はさらに悪いことになります)。これを行う最善の方法は、両方の操作を分離し、最初に削除する要素を「マーク」 (または並べ替え) し、次にそれらをベクトルから消去することです。

これは実際には、erase-remove イディオム( vector.erarse(std::remove(...), vector.end())) を使用して行うのが最適です。このイディオムは、最初に削除されていない要素を最初に使用std::remove(_if)してデータを再編成し、範囲の新しい終了を返します。次に、削除された要素を実際に削除するために使用できます。std::vector::erase. _ C++11 ラムダを使用すると、削除条件は非常に簡単に表現できます。

vector1.erase(std::remove_if(                        //erase range starting here
                  vector1.begin(), vector1.end(),    //iterate over whole vector
                  [&vector2](unsigned int i)         //call this for each element
                      { return vector2.at(i).var; }),  //return true to remove
              vector1.end());                        //erase up to old end

編集:std::vector::atちなみに、いつものように、単にではなく本当に必要かどうかを確認し[]、両方の意味を念頭に置いてください(特に前者のオーバーヘッドと後者の「おそらく不安」)。

于 2013-02-06T16:49:28.997 に答える