c++ - 如果双重注册,如何从 boost 树中删除 child ?

标签 c++ boost tree double

你能帮我解决以下问题吗?

我填充这个 finalTree = treeA + treeB

但是,问题在于treeB 的某些元素与treeA 的某些元素同名。因此,我可能会对某些 child 进行双重登记。

即。

    <category>
        <fruit type="banana">
              <characteristic>
                 <point v="0"/>
              </characteristic>
        </fruit>
        <fruit type="orange">
              <characteristic>
                 <point v="1"/>
               </characteristic>
        </fruit>
        <fruit type="banana">
              <characteristic>
                  <point v="2"/>
              </characteristic>
        </fruit>
        <fruit type="fig">
              <characteristic>
                <point v="3"/>
              </characteristic>
        </fruit>
    </category>

我想要实现的是删除香蕉的第一个条目并保留最后一个条目。 到目前为止我这样做:

boost::property_tree::ptree  & node = informationTree.add("information.fruitTypes", "");
node.add("<xmlattr>.type", fruit);
node.add_child("characteristic", char);

问题是我不知道如何删除它,因为我不知道下次复式输入是香蕉还是其他东西。我应该复制填充树吗?请问您有什么建议?

最佳答案

如果您只是构建树,您可以只使用 put_* 而不是 add_* 并且如果该元素已经存在,它会覆盖该名称的元素。

如果你有一棵树并且想删除某个子树的重复项,你必须手动执行,例如:

Live On Coliru

#include <boost/property_tree/xml_parser.hpp>
#include <iostream>
#include <map>
using boost::property_tree::ptree;

template <typename KeyF>
ptree nodup(ptree const& pt, KeyF key_accessor) {
    ptree filtered;
    std::map<std::string, std::reference_wrapper<ptree> > seen;

    for (auto& entry : pt) {
        auto key      = key_accessor(entry);
        auto previous = seen.find(key);

        if (seen.end() == previous)
            seen.emplace(key, filtered.add_child(entry.first, entry.second));
        else
            previous->second.get() = entry.second; // overwrite
    }

    return filtered;
}

int main() {
    ptree pt;
    {
        std::istringstream iss( "<category><fruit type=\"banana\"><characteristic><point v=\"0\"/></characteristic></fruit><fruit type=\"orange\"><characteristic><point v=\"1\"/></characteristic></fruit><fruit type=\"banana\"><characteristic><point v=\"2\"/></characteristic></fruit><fruit type=\"fig\"><characteristic><point v=\"3\"/></characteristic></fruit></category>");
        read_xml(iss, pt);
    }
    write_xml(std::cout, pt, boost::property_tree::xml_writer_make_settings<std::string>(' ', 4, "utf-8"));

    auto& subtree = pt.get_child("category");
    subtree = nodup(subtree, [](ptree::value_type const& item) { return item.second.get("<xmlattr>.type", ""); });

    write_xml(std::cout, pt, boost::property_tree::xml_writer_make_settings<std::string>(' ', 4, "utf-8"));
}

如果您更关心性能,您可以向后迭代并避免一些覆盖操作:

Live On Coliru

template <typename KeyF>
ptree nodup(ptree const& pt, KeyF key_accessor) {
    ptree filtered;
    std::map<std::string, std::reference_wrapper<ptree> > seen;

    for (auto entry = pt.rbegin(), last = pt.rend(); entry != last; ++entry) {
        auto key      = key_accessor(*entry);
        auto previous = seen.find(key);

        if (seen.end() == previous)
            seen.emplace(key, filtered.add_child(entry->first, entry->second));
    }

    return filtered;
}

但是,请记住,这可能会改变水果在子树中出现的顺序。

关于c++ - 如果双重注册,如何从 boost 树中删除 child ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43793107/

相关文章:

c++ - timer_create 给出内存泄漏问题 "Syscall param timer_create(evp) points to uninitialised byte(s)"

c++ - 可以像调用成员函数一样调用友元函数吗?

algorithm - 查找段的邻居(Bentley-Ottmann 算法)

java - 在树状结构中迭代 n 深度

c++ - 在 Qt View 中使用 QWidget

c++ - 案例 'p' 的问题 || 'P' : syntax within a switch statement in C++

c++ - 通过引用为 boost::shared_ptr 创建别名

c++: 复制一个 boost::array

c++ - 使用 boost::serialization 大大增加了二进制大小

c - 最长路径: Recursive Backtracking with Constraints in C