我试图根据特定情况从地图中删除一系列元素.我如何使用STL算法?
最初我想使用remove_if
但不可能因为remove_if不适用于关联容器.
是否有适用于地图的"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;
}
Run Code Online (Sandbox Code Playgroud)
Ste*_*lly 108
几乎.
for(; iter != endIter; ) {
if (Some Condition) {
aMap.erase(iter++);
} else {
++iter;
}
}
Run Code Online (Sandbox Code Playgroud)
如果你从中删除了一个元素,那么你最初会将迭代器增加两次 ; 你可能会跳过需要删除的元素.
这是我见过的常用算法,在许多地方都有使用和记录.
[编辑]你是正确的,擦除后迭代器失效,但只有迭代器引用被擦除的元素,其他迭代器仍然有效.因此在erase()调用中使用iter ++.
Iro*_*ior 70
我使用以下模板来做这件事.
namespace stuff {
template< typename ContainerT, typename PredicateT >
void erase_if( ContainerT& items, const PredicateT& predicate ) {
for( auto it = items.begin(); it != items.end(); ) {
if( predicate(*it) ) it = items.erase(it);
else ++it;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这不会返回任何内容,但它将从std :: map中删除项目.
用法示例:
// 'container' could be a std::map
// 'item_type' is what you might store in your container
using stuff::erase_if;
erase_if(container, []( item_type& item ) {
return /* insert appropriate test */;
});
Run Code Online (Sandbox Code Playgroud)
第二个例子(允许你传入一个测试值):
// 'test_value' is value that you might inject into your predicate.
// 'property' is just used to provide a stand-in test
using stuff::erase_if;
int test_value = 4; // or use whatever appropriate type and value
erase_if(container, [&test_value]( item_type& item ) {
return item.property < test_value; // or whatever appropriate test
});
Run Code Online (Sandbox Code Playgroud)
对于C++20上的用户,有用于map和unordered_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;
});
Run Code Online (Sandbox Code Playgroud)
现在,std::experimental::erase_if
在 header 中可用<experimental/map>
。
请参阅:http : //en.cppreference.com/w/cpp/experimental/map/erase_if
小智 5
这是一些优雅的解决方案。
for (auto it = map.begin(); it != map.end();)
{
(SomeCondition) ? map.erase(it++) : (++it);
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
51651 次 |
最近记录: |