2017-05-04 6 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

그냥 나무를 만드는 경우 add_* 대신 put_*을 사용할 수 있으며, 해당 이름으로 이미 존재하는 요소를 덮어 쓰게됩니다. 당신이 조금 경우

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

그러나, 이것은 잠재적으로 과일 서브 트리에 표시되는 순서를 변경 명심하십시오.