1. ホーム
  2. c++

[解決済み] remove_ifはstd::mapと同等です。

2022-06-08 09:53:56

質問

特定の条件に基づいて、マップからある範囲の要素を消去しようとしています。STLアルゴリズムを使ってどのように行うのでしょうか?

当初、私は remove_if を使おうと思ったのですが、remove_ifが連想コンテナには効かないので無理でした。

remove_ifと同等のアルゴリズムで、mapに対して動作するものはありますか?

簡単な方法として、mapをループして消去することを考えました。しかし、マップをループして消去することは安全なオプションなのでしょうか。

以下のような例を使ってみました。

bool predicate(const std::pair<int,std::string>& x)
{
    return x.first > 2;
}

int main(void) 
{

    std::map<int, std::string> aMap;

    aMap[2] = "two";
    aMap[3] = "three";
    aMap[4] = "four";
    aMap[5] = "five";
    aMap[6] = "six";

//      does not work, an error
//  std::remove_if(aMap.begin(), aMap.end(), predicate);

    std::map<int, std::string>::iterator iter = aMap.begin();
    std::map<int, std::string>::iterator endIter = aMap.end();

    for(; iter != endIter; ++iter)
    {
            if(Some Condition)
            {
                            // is it safe ?
                aMap.erase(iter++);
            }
    }

    return 0;
}

どのように解決するのですか?

ほとんどです。

for(; iter != endIter; ) {
     if (Some Condition) {
          iter = aMap.erase(iter);
     } else {
          ++iter;
     }
}

元々持っていたものは、イテレータをインクリメントするために 2回 を 2 回インクリメントするもので、消去する必要のある要素をスキップできる可能性があります。

これは、私が多くの場所で使用され、文書化されているのを見たことがある一般的なアルゴリズムです。

[しかし、消去された要素を参照するイテレータのみが有効であり、その他のイテレータはまだ有効です。したがって iter++ の中で erase() を呼び出します。