11

いくつかの基準に従ってアイテムを削除したいとします。まあ言ってみれば:

QMap<int, int> map;

値が奇数であるすべてのアイテムを削除したいと思います。イテレータを使用する場合:

for (auto it = map.begin(); it != map.end(); ++it)
    if (it.value() % 2 == 1)
        map.remove(it.key());

の呼び出しなので、このコードはおそらく間違っています。

map.remove(it.key()) 

イテレータを無効にします。各削除後にイテレータをリセットせずにこれを行うにはどうすればよいですか?

4

2 に答える 2

28

代わりに使用QMap::eraseすると、消去した要素の次の要素にイテレータが返されます。

for (auto it = map.begin(); it != map.end();)
    if (it.value() % 2 == 1)
        it = map.erase(it);
    else
        ++it;

もう 1 つの方法は、反復子で後置インクリメント演算子を使用することです。

for (auto it = map.begin(); it != map.end();)
    if (it.value() % 2 == 1)
        map.erase(it++);
    else
        ++it;

さらに別の方法 (おそらくあまり効率的ではありません) は、STLremove_copy_ifアルゴリズムを使用し、その後にswap:

bool valueIsOdd(int value) {return value % 2 == 1;}

QMap<int,int> b;
std::remove_copy_if(a.begin(), a.end(),
                    std::inserter(b, b.end()),
                    &valueIsOdd);
a.swap(b);

現時点では、最後の例をテストできません。

于 2012-07-27T14:11:00.993 に答える
5

eraseよりSTLに似た関数を使用したほうがよいでしょう。

  • 引数としてイテレータを使用するため、要素がどこにあるかがすでにわかっている場合でも、キーで要素を検索する時間を無駄にすることはありません。
  • イテレータを次の要素に戻すので、後で反復を続けることができます。

これを使用すると、ループを次のように正しく実装できます。

for (auto it = map.begin(); it != map.end(); /* don't increment here */) {
    if (it.value() % 2 == 1) {
        it = map.erase(it);
    } else {
        ++it;
    }
}

から同じ結果を得ることができると思いますがmap.remove((it++).key())、それはより遅くて厄介ですerase

于 2012-07-27T14:13:11.637 に答える