迭代多级boost树

迭代多级boost树,boost,tree,iteration,ptree,Boost,Tree,Iteration,Ptree,我的树是这样的: { "Library": { "L_ID": "1", "Book": { "B_ID": "1", "Title": "Moby Dick" }, "Book": { "B_ID": "2", "Title": "Jurassic Park" } }, "Library": { "L_ID": "2", "Book":

我的树是这样的:

{
"Library":
{
    "L_ID": "1",
     "Book":
     {
         "B_ID": "1",
         "Title": "Moby Dick"
     }, 
     "Book":
     {
         "B_ID": "2",
         "Title": "Jurassic Park"
     }
},
"Library":
{
    "L_ID": "2",
     "Book":
     {
         "B_ID": "1",
         "Title": "Velocity"
     }, 
     "Book":
     {
        "B_ID": "2",
        "Title": "Creeper"
     }
}
}
{
    "Libraries": [
        {
            "L_ID": 1,
            "Books": [
                {
                    "B_ID": 1,
                    "Title": "Moby Dick"
                },
                {
                    "B_ID": 2,
                    "Title": "Jurassic Park"
                }
            ]
        },
        {
            "L_ID": 2,
            "Books": [
                {
                    "B_ID": 1,
                    "Title": "Velocity"
                },
                {
                    "B_ID": 2,
                    "Title": "Creeper"
                }
            ]
        }
    ]
}
for (auto const &lib : libs["Libraries"])
    if (lib["L_ID"] == lib_num) 
        // we've found the library we want
#include "json.hpp"
#include <fstream>
#include <iostream>

using json = nlohmann::json;

std::string find_title(json lib_data, int lib_num, int book_num) {
    for (auto const &lib : lib_data["Libraries"])
        if (lib["L_ID"] == lib_num) 
            for (auto const &book : lib["Books"])
                if (book["B_ID"] == book_num)
                    return book["Title"];

    return "";
}

int main() {

    std::ifstream in("libraries.json");

    json lib_data;

    in >> lib_data;

    std::cout << find_title(lib_data, 1, 2);
}
namespace library_stuff {
    struct Book {
        int B_ID;
        std::string title;    
    };

    void from_json(json &j, Book &b) {
        b.B_ID = j["B_ID"];
        b.title = j["Title"];
    }
}
我想做的是遍历这些库。当我找到我要找的L_ID时,反复阅读书籍,直到找到我要找的B_ID。在这一点上,我想访问该部分中的所有叶子。 即,查找图书馆2、第1册、书名 注意:可能有比这更好的方法

boost::property_tree::ptree libraries = config_.get_child("Library");
for (const auto &lib : libraries)
{
   if (lib.second.get<uint16_6>("L_ID") == 2)
   { 
       //at this point, i know i'm the correct library...
       boost::property_tree::ptree books = lib.get_child("Book");
       for (const auto &book : books)
       {
            if (book.second.get<uint16_t>("B_ID") == 1)
            {
                 std::string mybook = book.second.get<std::string>("Title");
            }
        }
   }
boost::property\u tree::ptree libraries=config\u.get\u child(“库”);
用于(常量自动和库:库)
{
if(lib.second.get(“L_ID”)==2)
{ 
//在这一点上,我知道我是正确的图书馆。。。
boost::property_tree::ptree books=lib.get_child(“Book”);
用于(const auto&book:books)
{
if(book.second.get(“B_ID”)==1)
{
std::string mybook=book.second.get(“Title”);
}
}
}
我尝试查看第一个子树时就失败了。这里出了什么问题???

对于初学者来说,“JSON”有很大的缺陷。至少要修复缺少的引号和逗号:

{
    "Library": {
        "L_ID": "1",
        "Book": {
            "B_ID": "1",
            "Title": "Moby Dick"
        },
        "Book": {
            "B_ID": "2",
            "Title": "Jurassic Park"
        }
    },
    "Library": {
        "L_ID": "2",
        "Book": {
            "B_ID": "1",
            "Title": "Velocity"
        },
        "Book": {
            "B_ID": "2",
            "Title": "Creeper"
        }
    }
}
接下来,您似乎感到困惑。
get_child(“Library”)
以该名称获取第一个子节点,而不是包含名为“Library”的子节点的节点(顺便说一句,这将是根节点)

我是否可以建议添加一些抽象,也许还可以添加一些工具来通过一些名称/属性进行查询:

int main() {
    Config cfg;
    {
        std::ifstream ifs("input.txt");
        read_json(ifs, cfg.data_);
    }

    std::cout << "Book title: " << cfg.library(2).book(1).title() << "\n";
}
什么是
libraries()
?我们将深入探讨它,但让我们先看一下:

auto libraries() const {
    using namespace PtreeTools;
    return data_ | named("Library") | having("L_ID") | as<Library>();
}
我们在
books()
book(id)
中看到相同的模式来查找特定项目

魔法 magic使用增压范围适配器并潜伏在
PtreeTools

namespace PtreeTools {

    namespace detail {
        // ... 
    }

    auto named(std::string const& name) { 
        return detail::filtered(detail::KeyName{name});
    }

    auto having(std::string const& name) { 
        return detail::filtered(detail::HaveProperty{name});
    }

    template <typename T>
    auto as() { 
        return detail::transformed(detail::As<T>{});
    }
}
接下来,我们只定义知道如何筛选特定ptree节点的谓词:

    using Value = ptree::value_type;

    struct KeyName {
        std::string const _target;
        bool operator()(Value const& v) const {
            return v.first == _target;
        }
    };

    struct HaveProperty {
        std::string const _target;
        bool operator()(Value const& v) const {
            return v.second.get_optional<std::string>(_target).is_initialized();
        }
    };

@Sehe将您的JSON修复为语法正确,但我认为再深入一点是有意义的。考虑到您所表示的数据,拥有一个库数组将更有意义,每个库都包含一个书籍数组,提供如下数据:

{
"Library":
{
    "L_ID": "1",
     "Book":
     {
         "B_ID": "1",
         "Title": "Moby Dick"
     }, 
     "Book":
     {
         "B_ID": "2",
         "Title": "Jurassic Park"
     }
},
"Library":
{
    "L_ID": "2",
     "Book":
     {
         "B_ID": "1",
         "Title": "Velocity"
     }, 
     "Book":
     {
        "B_ID": "2",
        "Title": "Creeper"
     }
}
}
{
    "Libraries": [
        {
            "L_ID": 1,
            "Books": [
                {
                    "B_ID": 1,
                    "Title": "Moby Dick"
                },
                {
                    "B_ID": 2,
                    "Title": "Jurassic Park"
                }
            ]
        },
        {
            "L_ID": 2,
            "Books": [
                {
                    "B_ID": 1,
                    "Title": "Velocity"
                },
                {
                    "B_ID": 2,
                    "Title": "Creeper"
                }
            ]
        }
    ]
}
for (auto const &lib : libs["Libraries"])
    if (lib["L_ID"] == lib_num) 
        // we've found the library we want
#include "json.hpp"
#include <fstream>
#include <iostream>

using json = nlohmann::json;

std::string find_title(json lib_data, int lib_num, int book_num) {
    for (auto const &lib : lib_data["Libraries"])
        if (lib["L_ID"] == lib_num) 
            for (auto const &book : lib["Books"])
                if (book["B_ID"] == book_num)
                    return book["Title"];

    return "";
}

int main() {

    std::ifstream in("libraries.json");

    json lib_data;

    in >> lib_data;

    std::cout << find_title(lib_data, 1, 2);
}
namespace library_stuff {
    struct Book {
        int B_ID;
        std::string title;    
    };

    void from_json(json &j, Book &b) {
        b.B_ID = j["B_ID"];
        b.title = j["Title"];
    }
}
然后,如果可能的话,我会选择一个真正适合手头工作的库。Boost property tree并不是真正打算作为一个通用JSON库。如果你真的坚持,你可以将它推到这个角色上,但至少就你在问题中概述的内容而言,它会让你付出相当多的额外工作来获得你想要的

就我个人而言,我可能会使用它。使用它,我们可以更直接地处理一个解决方案。基本上,一旦它被解析为JSON文件,我们就可以像对待标准库中的普通集合一样对待结果——我们可以使用所有普通算法,基于范围的
for
循环等等。因此,我们可以加载JSON文件格式如下:

using json=nlohmann::json;

std::ifstream in("libraries.json");
json lib_data;

in >> lib_data;
然后我们可以在库中查找特定的ID号,代码如下:

{
"Library":
{
    "L_ID": "1",
     "Book":
     {
         "B_ID": "1",
         "Title": "Moby Dick"
     }, 
     "Book":
     {
         "B_ID": "2",
         "Title": "Jurassic Park"
     }
},
"Library":
{
    "L_ID": "2",
     "Book":
     {
         "B_ID": "1",
         "Title": "Velocity"
     }, 
     "Book":
     {
        "B_ID": "2",
        "Title": "Creeper"
     }
}
}
{
    "Libraries": [
        {
            "L_ID": 1,
            "Books": [
                {
                    "B_ID": 1,
                    "Title": "Moby Dick"
                },
                {
                    "B_ID": 2,
                    "Title": "Jurassic Park"
                }
            ]
        },
        {
            "L_ID": 2,
            "Books": [
                {
                    "B_ID": 1,
                    "Title": "Velocity"
                },
                {
                    "B_ID": 2,
                    "Title": "Creeper"
                }
            ]
        }
    ]
}
for (auto const &lib : libs["Libraries"])
    if (lib["L_ID"] == lib_num) 
        // we've found the library we want
#include "json.hpp"
#include <fstream>
#include <iostream>

using json = nlohmann::json;

std::string find_title(json lib_data, int lib_num, int book_num) {
    for (auto const &lib : lib_data["Libraries"])
        if (lib["L_ID"] == lib_num) 
            for (auto const &book : lib["Books"])
                if (book["B_ID"] == book_num)
                    return book["Title"];

    return "";
}

int main() {

    std::ifstream in("libraries.json");

    json lib_data;

    in >> lib_data;

    std::cout << find_title(lib_data, 1, 2);
}
namespace library_stuff {
    struct Book {
        int B_ID;
        std::string title;    
    };

    void from_json(json &j, Book &b) {
        b.B_ID = j["B_ID"];
        b.title = j["Title"];
    }
}
寻找某本书几乎是一样的:

for (auto const &book : lib["Books"])
   if (book["B_ID"] == book_num)
       // we've found the book we want

从这里开始,打印标题看起来像:
std::cout首先,我对json表示歉意。我还没有弄清楚如何将代码块复制到SO中并保持格式。我最终手工键入,这是一件痛苦的事情。我只使用json工作了几个小时,所以我想我对属性树做了一些假设不正确的行为。您的解决方案正是我想要的。我没有将JSON更改为任何“合理”的形式:)我只是添加了8个左右缺少的开头引号,可能还有2个逗号用于错误描述——我相信我已经纠正了。