2017-05-04 46 views
1

你能幫我解決以下問題嗎?如果雙重註冊,如何從助推樹中刪除孩子?

我填充這個finalTree = treeA + treeB

然而,問題是,treeB的一些元素與一些treeA同名。因此,我可能有一些孩子的雙註冊表。

即。

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

的問題是,我不知道如何刪除它,因爲我不知道複式是否將香蕉或下一次別的東西。我應該複製填充樹嗎?你有什麼建議嗎?

回答

0

如果您剛剛構建樹,則可以使用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; 
} 

但是,請記住,這可能會改變其中的水果出現在樹的順序。