【问题标题】:How to remove key from poco json while iterating it?如何在迭代时从 poco json 中删除密钥?
【发布时间】:2019-06-24 13:07:24
【问题描述】:

如何在迭代时从 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 中,erase 返回下一次迭代的有效迭代器,但我找不到 Poco json 类似的东西。

【问题讨论】:

    标签: c++ poco-libraries


    【解决方案1】:

    std::map::erase 将迭代器返回到自 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 使迭代器无效?

    一些来自源的sn-p代码:

    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
    }
    

    【讨论】:

    • @nader 所以你应该提供 mvc 示例,你的基于 range-for 循环的代码由于该循环的工作机制而无法工作 - 迭代器在被擦除后递增,并且第二个代码不能编译。
    • 我在第二个代码中添加了注释,说明 Poco 没有类似 std map 擦除的机制。这只是一个例子。我在寻找像 std mape erase 这样的机制来删除,但我在 Poco 中找不到
    • @nader 我编辑了我的答案。您知道为什么在使用 range-for 循环时代码会崩溃。
    【解决方案2】:

    你可以在 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;
    }
    

    【讨论】:

    • 我无法修改。这对我来说是一种约束。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-01
    相关资源
    最近更新 更多