本文介绍了如何返回一个boost :: property_tree的叶节点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有其中所有的数据存储在其叶节点的属性树。树,但是,具有复杂的结构。我想现在要做的是:


  1. 让所有(只有)叶子树的节点,它们包含的数据和

  2. 召回导致相应叶节点的路径

最后,我想收到一个键/值对所有的(只有)叶节点,其中键包含到节点的完整路径和值包含节点的值。

我的问题是:


  1. 难道还有比在整个树递归遍历,存储相应的路径,并宣读了没有孩子节点的值(即一个更方便的方法的 get_leaves()的功能)?

  2. 如果我有一些指针子树( ptree中的变量的迭代器的,无论..)给定的树,有没有一种方法可以轻松地确定相对路径树里面的那个子树的?


解决方案

我只是写一些辅助功能。他们真的并不难。这里是一个完全通用的树探访功能任选花费predicate:

 模板< typename的树,类型名楼类型名称preD / * =布尔(*)(树常量和放大器;)* /类型名称PathType =标准::字符串>
无效visit_if(树&安培;树,女常量和放大器; F,preD常量和放大器; P,PathType常量和放大器;路径= PathType())
{
    如果(P(树))
        F(路径树);    为(自动&安培;儿童:树)
        如果(path.empty())
            visit_if(child.second,F,P,child.first);
        其他
            visit_if(child.second,F,P,路径+ + child.first。);
}模板< typename的树,类型名楼类型名PathType =标准::字符串>
无效访问(树&安培;树,女常量和放大器; F,PathType常量和放大器;路径= PathType())
{
    visit_if(树,F [](树常量和放大器;){返回true;},路径);
}

您可以用predicate使用它像

 的#include<升压/ property_tree / ptree.hpp>布尔is_leaf(升压:: property_tree :: ptree中常量和放大器; PT){
    返回pt.empty();
}

和这里是一个简单的演示:

 的#include<&iostream的GT;
诠释的main()
{
    使用boost :: property_tree :: ptree中;
    汽车工艺= [](ptree中:: path_type常量和放大器;路径,ptree中常量和放大器;节点){
            性病::法院LT&;< 留出节点<其中p path.dump()&所述;&下; '有价值'<< node.get_value()下;&下; '\\ n;
        };    ptree中PT;
    pt.put(some.deeply.nested.values​​,公正);
    pt.put(for.the.sake.of.demonstration,42);    visit_if(PT,过程,is_leaf);
}

打印:

 叶子节点在some.deeply.nested.values​​'的值'只是'
在for.the.sake.of.demonstration'离开节点的值'42'

更新

就指出了问题的后半部分。这里是如何使用相同访客做到这一点:

 模板< typename的树>
推动::可选<标准::字符串> path_of_optional(树常量和放大器;树,树常量和放大器;目标){
    推动::可选<标准::字符串>结果;    访问(树[&安培;(标准::字符串常量和放大器;路径,树常量和放大器;电流){如果(安培;目标==&安培;电流)结果=路径;});    返回结果;
}模板< typename的树>
标准::字符串path_of(树常量和放大器;树,树常量和放大器;目标){
    汽车R = path_of_optional(树,目标);
    如果抛出std :: range_error(path_of)(R!);
    返回* R;
}

和演示

 的std ::法院LT&;< 从节点路径:<< path_of(PT,pt.get_child(for.the.sake))≤;&下; \\ n;

I have a property tree where all the data is stored in its leaf nodes. The Tree, however, has a complex structure. What I want to do now is:

  1. get all (and only the) leaf nodes of the tree, for they contain the data and
  2. recall the path leading to the respective leaf node

Eventually, I want to receive a key/value pair of all (and only the) leaf nodes where the key contains the complete path to the node and the value contains the node's value.

My questions are:

  1. Is there a more convenient way than to recursively iterate through the whole tree, store the respective path and read out the values of the nodes that don't have children (i.e. a "get_leaves()" function)?
  2. If I have some pointer to a subtree (ptree variable, iterator, whatever..) of a given tree, is there a method to easily determine the relative path of that subtree inside the tree?
解决方案

I'd just write some helper functions. They're really not that difficult. Here's a completely generic tree visitation function that optionally takes a predicate:

template <typename Tree, typename F, typename Pred/* = bool(*)(Tree const&)*/, typename PathType = std::string>
void visit_if(Tree& tree, F const& f, Pred const& p, PathType const& path = PathType())
{
    if (p(tree))
        f(path, tree);

    for(auto& child : tree)
        if (path.empty())
            visit_if(child.second, f, p, child.first);
        else
            visit_if(child.second, f, p, path + "." + child.first);
}

template <typename Tree, typename F, typename PathType = std::string>
void visit(Tree& tree, F const& f, PathType const& path = PathType())
{
    visit_if(tree, f, [](Tree const&){ return true; }, path);
}

You can use it with a predicate like

#include <boost/property_tree/ptree.hpp>

bool is_leaf(boost::property_tree::ptree const& pt) {
    return pt.empty();
}

And here's a simple demo:

#include <iostream>
int main()
{
    using boost::property_tree::ptree;
    auto process = [](ptree::path_type const& path, ptree const& node) {
            std::cout << "leave node at '" << path.dump() << "' has value '" << node.get_value("") << "'\n";
        };

    ptree pt;
    pt.put("some.deeply.nested.values", "just");
    pt.put("for.the.sake.of.demonstration", 42);

    visit_if(pt, process, is_leaf);
}

Prints:

leave node at 'some.deeply.nested.values' has value 'just'
leave node at 'for.the.sake.of.demonstration' has value '42'

UPDATE

Just noted the second half of the question. here's how to do it using the same visitor:

template <typename Tree>
boost::optional<std::string> path_of_optional(Tree const& tree, Tree const& target) {
    boost::optional<std::string> result;

    visit(tree, [&](std::string const& path, Tree const& current) { if (&target == &current) result = path; });

    return result;
}

template <typename Tree>
std::string path_of(Tree const& tree, Tree const& target) {
    auto r = path_of_optional(tree, target);
    if (!r) throw std::range_error("path_of");
    return *r;
}

And a demo Live On Coliru

std::cout << "Path from node: " << path_of(pt, pt.get_child("for.the.sake")) << "\n";

这篇关于如何返回一个boost :: property_tree的叶节点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 08:04