2011-11-16 16 views
15

मैंने boost :: property_tree के लिए प्रलेखन के माध्यम से पढ़ा है और किसी अन्य ptree के साथ ptree को अपडेट या मर्ज करने का कोई तरीका नहीं मिला है। मैं यह कैसे करु?मैं बूस्ट :: property_tree :: ptree कैसे विलय/अपडेट कर सकता हूं?

नीचे दिए गए कोड को देखते हुए, update_ptree फ़ंक्शन कैसा दिखता है?

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

class A 
{ 
    ptree pt_; 
public: 
    void set_ptree(const ptree &pt) 
    { 
    pt_ = pt; 
    }; 
    void update_ptree(const ptree &pt) 
    { 
    //How do I merge/update a ptree? 
    }; 
    ptree get_ptree() 
    { 
    return pt_; 
    }; 
}; 

int main() 
{ 
    A a; 
    ptree pt; 
    pt.put<int>("first.number",0); 
    pt.put<int>("second.number",1); 
    pt.put<int>("third.number",2); 
    a.set_ptree(pt); 
    ptree pta = a.get_ptree(); 

    //prints "0 1 2" 
    std::cout << pta.get<int>("first.number") << " " 
      << pta.get<int>("second.number") << " " 
      << pta.get<int>("third.number") << "\n"; 


    ptree updates; 
    updates.put<int>("first.number",7); 
    a.update_ptree(updates); 
    pta = a.get_ptree(); 

    //Because the update_tree function doesn't do anything it just prints "0 1 2". 
    //I would like to see "7 1 2" 
    std::cout << pta.get<int>("first.number") << " " 
      << pta.get<int>("second.number") << " " 
      << pta.get<int>("third.number") << "\n"; 

    return 0; 
} 

मैं नए ptree से अधिक पुनरावृत्ति और का उपयोग कर "डाल" मूल्यों को सम्मिलित करने के बारे में सोचा है। लेकिन "put" को एक प्रकार की आवश्यकता है और मुझे नहीं पता कि नई जानकारी से उस जानकारी को कैसे प्राप्त किया जाए और इसे पुराने ptree के लिए तर्क के रूप में उपयोग करें।

एक बात मैं update_ptree समारोह में की कोशिश की है उपयोग कर रहा है:

pt_.add_child(".",pt); 

मूल रूप से मैं pt_ के मार्ग पर एक बच्चे के रूप में pt जोड़ने के लिए प्रयास करें। दुर्भाग्य से यह काम नहीं लग रहा है।

कोई विचार?

मैं किसी भी मदद के लिए आभारी हूं।

धन्यवाद।

(मैं इस सवाल का टैग property_tree और ptree जोड़ने की कोशिश की, लेकिन मैं की अनुमति नहीं थी)

उत्तर

17

मुझे लगता है कि आपको रिक्त रूप से property_tree को पार करना होगा।

आप एक समारोह है कि रिकर्सिवली प्रत्येक नोड पर दोहराता है और प्रत्येक नोड के लिए एक विधि कॉल को परिभाषित कर सकते हैं:

template<typename T> 
void traverse_recursive(const boost::property_tree::ptree &parent, const boost::property_tree::ptree::path_type &childPath, const boost::property_tree::ptree &child, T &method) 
{ 
    using boost::property_tree::ptree; 

    method(parent, childPath, child); 
    for(ptree::const_iterator it=child.begin();it!=child.end();++it) { 
    ptree::path_type curPath = childPath/ptree::path_type(it->first); 
    traverse_recursive(parent, curPath, it->second, method); 
    } 
} 

हम कॉल करने के लिए में एक सरल समारोह को परिभाषित कर सकते पिछले एक:

template<typename T> 
void traverse(const boost::property_tree::ptree &parent, T &method) 
{ 
    traverse_recursive(parent, "", parent, method); 
} 

अब, आप केवल एक नोड को मर्ज करने के लिए एक विधि जोड़ने के लिए कक्षा ए को संशोधित कर सकते हैं और update_ptree विधि भर सकते हैं:

#include <boost/bind.hpp> 

class A { 
    ptree pt_; 

public: 
    void set_ptree(const ptree &pt) {  
    pt_ = pt; 
    } 

    void update_ptree(const ptree &pt) { 
    using namespace boost; 
    traverse(pt, bind(&A::merge, this, _1, _2, _3)); 
    } 

    ptree get_ptree() { 
    return pt_; 
    } 

protected: 
    void merge(const ptree &parent, const ptree::path_type &childPath, const ptree &child) { 
    pt_.put(childPath, child.data()); 
    }  
}; 

एकमात्र सीमा यह है कि एक ही पथ के साथ कई नोड्स संभव है। उनमें से प्रत्येक का उपयोग किया जाएगा, लेकिन केवल अंतिम व्यक्ति विलय हो जाएगा।

+0

धन्यवाद। यह एक दिलचस्प समाधान है। एक संकलन संकलित करने वाला होगा! लेकिन आपका क्या मतलब है "एक ही पथ के साथ कई नोड्स संभव है"? Tree_1 = "a.b.c" = 0 अद्यतन पेड़ Tree_2 = "a.b.c" = 1, "a.b.d" = 2। केवल "a.b.d" = 2 अपडेट किया जाएगा? (डीबग और देखें) – mantler

+0

एक ही पथ के साथ एक से अधिक नोड होना संभव है। जब Tree_1 में "a.b.c" = 1, "a.b.c" = 2 और Tree_2 में "a.b.c" = 1 होता है, तो Tree_1 के साथ Tree_2 को अपडेट करने के बाद, Tree_2 में "a.b.c" = 2 होगा। –

+0

यह कोड का एक बहुत अच्छा टुकड़ा है। आप कैसे जानते थे कि यह ऑपरेटर path_type पर काम करेगा ?: ptree :: path_type curPath = childPath/ptree :: path_type (it-> पहले); 'मैं नहीं देख सकता कि यह दस्तावेज दस्तावेज में परिभाषित किया गया है। – 2NinerRomeo

5

Boost.Property पेड़ अभी तक इस का समर्थन नहीं करता,: boost.org/doc/libs/1_48_0/doc/html/property_tree/appendices.html। भावी कार्य अनुभाग देखें।

गणितीय संबंध: ptree अंतर, संघ, चौराहे।

एक अपडेट केवल एक संघ के बाद एक अंतर है। a = (a - b) + b

सामान्य समाधान के लिए रिक्रीवली अद्यतन पीआरटीई और प्रत्येक पत्ता डालने की आवश्यकता होगी।

हालांकि put_child के साथ एक अच्छा पर्याप्त समाधान बनाया जा सकता है। सामान्य समाधान की जटिलता के बिना, आपको यह सब कुछ चाहिए।

void merge(ptree& pt, const ptree& updates) 
{ 
    BOOST_FOREACH(auto& update, updates) 
    { 
     pt.put_child(update.first, update.second); 
    } 
} 

अच्छे पर्याप्त समाधान में दो सीमाएं हैं, संयोग से वे ini_parser की समान सीमाएं हैं।

  • पेड़ केवल दो परतें (जैसे "first.number", लेकिन "first.again.number")
  • मूल्यों केवल पत्र-गांठ में संग्रहित किया जा सकता हो सकता है।
+0

धन्यवाद। मैं कोशिश करूँगा और देखता हूं कि यह कैसे काम करता है। यह दिलचस्प है कि आप "पेड़ केवल दो परतों के बारे में क्या कह सकते हैं ..", मैंने इसके बारे में सोचा नहीं था। तो यह हो सकता है कि मैं जो करना चाहता हूं (मनमाने ढंग से वृक्ष गहराई के लिए) के आसपास कोई काम या "जेनेरिक" एल्गोरिदम नहीं है? – mantler

संबंधित मुद्दे