簡體   English   中英

如何返回boost :: property_tree的葉節點

[英]How return leaf nodes of a boost::property_tree

我有一棵屬性樹,所有數據都存儲在其葉節點中。 但是,樹具有復雜的結構。 我現在想做的是:

  1. 獲取樹的所有(且僅)葉節點,因為它們包含數據和
  2. 重新調用通向各個葉節點的路徑

最終,我希望接收所有(且僅是)葉節點的鍵/值對,其中鍵包含指向節點的完整路徑,而值包含節點的值。

我的問題是:

  1. 除了遞歸遍歷整棵樹,存儲各自的路徑並讀出沒有子節點的值(即“ get_leaves()函數”)之外,還有沒有更方便的方法?
  2. 如果我有指向給定樹的子樹的指針( ptree變量, 迭代器等),是否有一種方法可以輕松確定樹內該子樹的相對路徑?

我只是寫一些輔助函數。 他們真的沒有那么困難。 這是一個完全通用的樹訪問函數,可以選擇使用謂詞:

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);
}

您可以將其與謂詞一起使用

#include <boost/property_tree/ptree.hpp>

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

這是一個簡單的演示:

生活在Coliru

#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);
}

打印:

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

UPDATE

剛剛指出了問題的后半部分。 使用同一位訪問者的操作方法如下:

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;
}

和演示Live On Coliru

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM