StackOverflow上有几个答案表明以下循环是从std::unordered_map
中删除满足某个谓词pred
的元素的好方法:
std::unordered_map<...> m;
auto it = m.begin();
while (it != m.end())
{
if (pred(*it))
it = m.erase(it);
else
++it;
}
我对C ++ 11特别感兴趣(而不是C ++ 14),以下不祥的note on cppreference.com表明上述循环依赖于未定义的行为,可能无法在C +中运行毕竟+11:
保留未被删除元素的顺序(这样可以在迭代容器时删除单个元素)(自C ++ 14开始)
另请参阅Title 2356. Stability of erasure in unordered associative containers,其中包含对第754页Working Draft N3797第14项请求的措辞更改(附加短语开头&#34;,并保留相对顺序......&#34;)
这个措辞与N3797有关。
按照指示修改[unord.req],p14:
-14- insert和emplace成员不应影响对容器元素的引用的有效性,但可能使所有迭代器无效 容器。擦除成员只能使迭代器和 对擦除元素的引用,并保留相对的顺序 未被删除的元素。
如果我对cppreference.com的注释的解释是正确的,并且上面的循环依赖于C ++ 11中未定义的行为,那么在C ++ 11中解决这个问题的最有效方法是什么? / p>
答案 0 :(得分:14)
为了遵守C ++ 11,您很可能会对如何解决这个问题有所限制。您的选择基本上归结为:
迭代unordered_map
并构建一个要删除的键列表,如下所示:
//std::unordered_map<...> mymap;
std::vector<decltype(mymap)::key_type> vec;
for (auto&& i : mymap)
if (/*compare i*/)
vec.emplace_back(i.first);
for (auto&& key : vec)
mymap.erase(key);
迭代对象并重置如果我们找到要删除的内容 - 我真的只推荐这个小数据集。那些觉得goto的人是无条件的坏人,嗯,这个选择可以说是糟糕的。
//std::unordered_map<...> mymap;
reset:
for (auto&& i : mymap)
if (/*compare i*/) {
mymap.erase(i.first);
goto reset;
}
作为一个 out 选项,你也可以创建一个新的unordered_map
并移动你想要保留的元素。当您有更多要删除而不是保留时,这可以说是一个不错的选择。
//std::unordered_map<...> mymap;
decltype(mymap) newmap;
for (auto&& i : mymap)
if (/*i is an element we want*/)
newmap.emplace(std::move(i));
mymap.swap(newmap);
答案 1 :(得分:1)
嗯,你可以随时这样做:
std::unordered_map<...> m;
std::vector<key_type> needs_removing;
for(auto&& pair : m)
{
if (pred(pair))
needs_removing.push_back(pair.first);
}
for(auto&& key : needs_removing)
m.erase(key);
速度较慢,但复杂程度相同。
答案 2 :(得分:1)
使用 erase_if (c ++ 20)而不是循环(请参见https://en.cppreference.com/w/cpp/container/unordered_map/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;
});
答案 3 :(得分:-3)
首先参考stl-algorithms
这个似乎是想要的: http://www.cplusplus.com/reference/algorithm/remove_if/
概述: http://www.cplusplus.com/reference/algorithm/
修改强> cppreference在网站底部有一个类似的例子。 它适用于c ++ 11编译器。