等效于 std::map 的 remove_if

新手上路,请多包涵

我试图根据特定条件从地图中删除一系列元素。我如何使用 STL 算法来做到这一点?

最初我想使用 remove_if 但这是不可能的,因为 remove_if 不适用于关联容器。

是否有任何适用于 map 的“remove_if”等效算法?

作为一个简单的选择,我想循环遍历地图并擦除。但是循环遍历地图并擦除安全选项吗?(因为迭代器在擦除后变得无效)

我使用了以下示例:

 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;
}

原文由 aJ. 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

几乎。

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

如果您确实从中删除了一个元素,那么您最初的操作会使迭代器增加 _两次_;您可能会跳过需要删除的元素。

这是我在许多地方看到使用和记录的常用算法。

[编辑]您是正确的,迭代器在擦除后无效,但只有引用被擦除元素的迭代器,其他迭代器仍然有效。因此在 erase() 调用中使用 iter++ —。

原文由 Steve Folly 发布,翻译遵循 CC BY-SA 4.0 许可协议

对于 C++20 上的那些,有用于 mapunordered_map 的内置 std::erase_if 函数:

 std::unordered_map<int, char> data {{1, 'a'},{2, 'b'},{3, 'c'},{4, 'd'},
                                    {5, 'e'},{4, 'f'},{5, 'g'},{5, 'g'}};

const auto count = std::erase_if(data, [](const auto& item) {
    auto const& [key, value] = item;
    return (key & 1) == 1;
});

原文由 MartinBG 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏