如何在迭代时从 poco json 中删除密钥?
How to remove key from poco json while iterating it?
如何在迭代时从 Poco json 中删除密钥?喜欢:
Poco::JSON::Object::Ptr poco_json;
for (auto& objs : *poco_json)
{
// do something
if (objs.first == "specific key")
poco_json->remove(key);
}
或
Poco::JSON::Object::Ptr poco_json;
for(auto it = poco_json->begin();it != poco_json->end();)
{
// do something
if (it->first == "specific key")
it = poco_json->remove(it->first);//error : poco didn't have something like this
else
++it;
}
问题是从 json 中删除一个键后,它会使迭代器失效。我知道在 std::map 中擦除 return 下一次迭代的有效迭代器,但我找不到与 Poco json 类似的东西。
std::map::erase
returns 从 C++11 开始到下一个项目的迭代器,在 C++11 之前你可以这样擦除项目:
for (auto it = m.begin(); it != m.end(); ) {
if (it->first == someKey)
m.erase(it++); // use post-increment,pass copy of iterator, advance it
else
++it;
}
您可以在从 Poco::JSON::Object
中删除密钥时以类似的方式执行此操作。您在哪里读到 remove
使迭代器无效?
来自源代码的一些片段代码:
class JSON_API Object {
typedef std::map<std::string, Dynamic::Var> ValueMap; // <--- map
//...
Iterator begin();
/// Returns begin iterator for values.
Iterator end();
/// Returns end iterator for values.
void remove(const std::string& key);
/// Removes the property with the given key.
ValueMap _values; // <---
};
inline Object::Iterator Object::begin()
{
return _values.begin();
}
inline Object::Iterator Object::end()
{
return _values.end();
}
inline void Object::remove(const std::string& key)
{
_values.erase(key); // <--- erase is called on map, so iteratos are not invalidated
if (_preserveInsOrder)
{
KeyList::iterator it = _keys.begin();
KeyList::iterator end = _keys.end();
for (; it != end; ++it)
{
if (key == (*it)->first)
{
_keys.erase(it);
break;
}
}
}
_modified = true;
}
您可以将循环重写为:
for(auto it = poco_json->begin();it != poco_json->end();)
{
// do something
if (it->first == "specific key")
{
auto copyIt = it++;
poco_json->remove(copyIt->first);
}
else
++it;
}
编辑
为什么您的代码在 range-for 循环中不起作用:
for (auto& objs : *poco_json)
{
// do something
if (objs.first == "specific key")
poco_json->remove(key);
}
翻译成
for (auto it = poco_json->begin(); it != poco_json->end(); ++it)
{
// do something
if (it->first == "specific key")
poco_json->remove(it->first);
// remove is called, it is erased from inner map
// ++it is called on iterator which was invalidated,
// code crashes
}
您可以在Poco中修改这段代码:
inline Iterator Object::remove(const std::string& key)
{
auto ret_it = _values.erase(key);
if (_preserveInsOrder)
{
KeyList::iterator it = _keys.begin();
KeyList::iterator end = _keys.end();
for (; it != end; ++it)
{
if (key == (*it)->first)
{
_keys.erase(it);
break;
}
}
}
_modified = true;
return ret_it;
}
如何在迭代时从 Poco json 中删除密钥?喜欢:
Poco::JSON::Object::Ptr poco_json;
for (auto& objs : *poco_json)
{
// do something
if (objs.first == "specific key")
poco_json->remove(key);
}
或
Poco::JSON::Object::Ptr poco_json;
for(auto it = poco_json->begin();it != poco_json->end();)
{
// do something
if (it->first == "specific key")
it = poco_json->remove(it->first);//error : poco didn't have something like this
else
++it;
}
问题是从 json 中删除一个键后,它会使迭代器失效。我知道在 std::map 中擦除 return 下一次迭代的有效迭代器,但我找不到与 Poco json 类似的东西。
std::map::erase
returns 从 C++11 开始到下一个项目的迭代器,在 C++11 之前你可以这样擦除项目:
for (auto it = m.begin(); it != m.end(); ) {
if (it->first == someKey)
m.erase(it++); // use post-increment,pass copy of iterator, advance it
else
++it;
}
您可以在从 Poco::JSON::Object
中删除密钥时以类似的方式执行此操作。您在哪里读到 remove
使迭代器无效?
来自源代码的一些片段代码:
class JSON_API Object {
typedef std::map<std::string, Dynamic::Var> ValueMap; // <--- map
//...
Iterator begin();
/// Returns begin iterator for values.
Iterator end();
/// Returns end iterator for values.
void remove(const std::string& key);
/// Removes the property with the given key.
ValueMap _values; // <---
};
inline Object::Iterator Object::begin()
{
return _values.begin();
}
inline Object::Iterator Object::end()
{
return _values.end();
}
inline void Object::remove(const std::string& key)
{
_values.erase(key); // <--- erase is called on map, so iteratos are not invalidated
if (_preserveInsOrder)
{
KeyList::iterator it = _keys.begin();
KeyList::iterator end = _keys.end();
for (; it != end; ++it)
{
if (key == (*it)->first)
{
_keys.erase(it);
break;
}
}
}
_modified = true;
}
您可以将循环重写为:
for(auto it = poco_json->begin();it != poco_json->end();)
{
// do something
if (it->first == "specific key")
{
auto copyIt = it++;
poco_json->remove(copyIt->first);
}
else
++it;
}
编辑 为什么您的代码在 range-for 循环中不起作用:
for (auto& objs : *poco_json)
{
// do something
if (objs.first == "specific key")
poco_json->remove(key);
}
翻译成
for (auto it = poco_json->begin(); it != poco_json->end(); ++it)
{
// do something
if (it->first == "specific key")
poco_json->remove(it->first);
// remove is called, it is erased from inner map
// ++it is called on iterator which was invalidated,
// code crashes
}
您可以在Poco中修改这段代码:
inline Iterator Object::remove(const std::string& key)
{
auto ret_it = _values.erase(key);
if (_preserveInsOrder)
{
KeyList::iterator it = _keys.begin();
KeyList::iterator end = _keys.end();
for (; it != end; ++it)
{
if (key == (*it)->first)
{
_keys.erase(it);
break;
}
}
}
_modified = true;
return ret_it;
}