multi_index composite_key 替换为迭代器

发布于 2024-09-01 06:32:57 字数 3256 浏览 7 评论 0原文

是否有办法循环访问 boost::multi_index 中的索引并执行替换?

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>

using namespace boost::multi_index;
using namespace std;

struct name_record
{

  public:

  name_record(string given_name_,string family_name_,string other_name_)
  {
      given_name=given_name_;
      family_name=family_name_;
      other_name=other_name_;
  }

  string given_name;
  string family_name;
  string other_name;

  string get_name() const { return given_name + " " + family_name + " " + other_name; }

  void setnew(string chg)
  {
      given_name = given_name + chg;
      family_name = family_name + chg;
  }

};

struct NameIndex{};

typedef multi_index_container<
  name_record,
  indexed_by<
    ordered_non_unique<
      tag<NameIndex>,
      composite_key
      <
        name_record,
        BOOST_MULTI_INDEX_MEMBER(name_record,string, name_record::given_name),
        BOOST_MULTI_INDEX_MEMBER(name_record,string, name_record::family_name)
      >
    >
  >
> name_record_set;

typedef boost::multi_index::index<name_record_set,NameIndex>::type::iterator IteratorType;
typedef boost::multi_index::index<name_record_set,NameIndex>::type NameIndexType;

void printContainer(name_record_set & ns)
{
  cout << endl << "PrintContainer" << endl << "-------------" << endl;
  IteratorType it1 = ns.begin();
  IteratorType it2 = ns.end  ();

  while (it1 != it2)
  {
       cout<<it1->get_name()<<endl;
       it1++;
  }
  cout << "--------------" << endl << endl;

}


void modifyContainer(name_record_set & ns)
{
  cout << endl << "ModifyContainer" << endl << "-------------" << endl;
  IteratorType it3;
  IteratorType it4;

  NameIndexType & idx1 = ns.get<NameIndex>();
  IteratorType it1 = idx1.begin();
  IteratorType it2 = idx1.end();

  while (it1 != it2)
  {
        cout<<it1->get_name()<<endl;
        name_record nr = *it1;

        nr.setnew("_CHG");
        bool res = idx1.replace(it1,nr);
        cout << "result is: " << res << endl;
        it1++;
  }
  cout << "--------------" << endl << endl;
}

int main()
{
  name_record_set ns;

  ns.insert( name_record("Joe","Smith","ENTRY1")          );
  ns.insert( name_record("Robert","Brown","ENTRY2")       );
  ns.insert( name_record("Robert","Nightingale","ENTRY3") );
  ns.insert( name_record("Marc","Tuxedo","ENTRY4")        );

  printContainer  (ns);
  modifyContainer (ns);
  printContainer  (ns);

  return 0;
}



PrintContainer
-------------
Joe Smith ENTRY1
Marc Tuxedo ENTRY4
Robert Brown ENTRY2
Robert Nightingale ENTRY3
--------------


ModifyContainer
-------------
Joe Smith ENTRY1
result is: 1
Marc Tuxedo ENTRY4
result is: 1
Robert Brown ENTRY2
result is: 1
--------------


PrintContainer
-------------
Joe_CHG Smith_CHG ENTRY1
Marc_CHG Tuxedo_CHG ENTRY4
Robert Nightingale ENTRY3
Robert_CHG Brown_CHG ENTRY2
--------------

Is there anyway to loop through an index in a boost::multi_index and perform a replace?

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/composite_key.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>

using namespace boost::multi_index;
using namespace std;

struct name_record
{

  public:

  name_record(string given_name_,string family_name_,string other_name_)
  {
      given_name=given_name_;
      family_name=family_name_;
      other_name=other_name_;
  }

  string given_name;
  string family_name;
  string other_name;

  string get_name() const { return given_name + " " + family_name + " " + other_name; }

  void setnew(string chg)
  {
      given_name = given_name + chg;
      family_name = family_name + chg;
  }

};

struct NameIndex{};

typedef multi_index_container<
  name_record,
  indexed_by<
    ordered_non_unique<
      tag<NameIndex>,
      composite_key
      <
        name_record,
        BOOST_MULTI_INDEX_MEMBER(name_record,string, name_record::given_name),
        BOOST_MULTI_INDEX_MEMBER(name_record,string, name_record::family_name)
      >
    >
  >
> name_record_set;

typedef boost::multi_index::index<name_record_set,NameIndex>::type::iterator IteratorType;
typedef boost::multi_index::index<name_record_set,NameIndex>::type NameIndexType;

void printContainer(name_record_set & ns)
{
  cout << endl << "PrintContainer" << endl << "-------------" << endl;
  IteratorType it1 = ns.begin();
  IteratorType it2 = ns.end  ();

  while (it1 != it2)
  {
       cout<<it1->get_name()<<endl;
       it1++;
  }
  cout << "--------------" << endl << endl;

}


void modifyContainer(name_record_set & ns)
{
  cout << endl << "ModifyContainer" << endl << "-------------" << endl;
  IteratorType it3;
  IteratorType it4;

  NameIndexType & idx1 = ns.get<NameIndex>();
  IteratorType it1 = idx1.begin();
  IteratorType it2 = idx1.end();

  while (it1 != it2)
  {
        cout<<it1->get_name()<<endl;
        name_record nr = *it1;

        nr.setnew("_CHG");
        bool res = idx1.replace(it1,nr);
        cout << "result is: " << res << endl;
        it1++;
  }
  cout << "--------------" << endl << endl;
}

int main()
{
  name_record_set ns;

  ns.insert( name_record("Joe","Smith","ENTRY1")          );
  ns.insert( name_record("Robert","Brown","ENTRY2")       );
  ns.insert( name_record("Robert","Nightingale","ENTRY3") );
  ns.insert( name_record("Marc","Tuxedo","ENTRY4")        );

  printContainer  (ns);
  modifyContainer (ns);
  printContainer  (ns);

  return 0;
}



PrintContainer
-------------
Joe Smith ENTRY1
Marc Tuxedo ENTRY4
Robert Brown ENTRY2
Robert Nightingale ENTRY3
--------------


ModifyContainer
-------------
Joe Smith ENTRY1
result is: 1
Marc Tuxedo ENTRY4
result is: 1
Robert Brown ENTRY2
result is: 1
--------------


PrintContainer
-------------
Joe_CHG Smith_CHG ENTRY1
Marc_CHG Tuxedo_CHG ENTRY4
Robert Nightingale ENTRY3
Robert_CHG Brown_CHG ENTRY2
--------------

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

后eg是否自 2024-09-08 06:32:57
while (it1 != it2)
{
      cout<<it1->get_name()<<endl;
      name_record nr = *it1;

      nr.setnew("_CHG");
      bool res = idx1.replace(it1,nr);
      cout << "result is: " << res << endl;
      it1++;
}

这段代码的问题在于,一旦替换了元素 x,它就会自动重新排序到新位置,因此 it1 会一直指向 x,“跳跃”序列并可能跳过或重新访问元素。

解决方案是在开始替换之前添加一个间接级别并收集所有元素的迭代器:

#include <vector>
#include <boost/iterator/counting_iterator.hpp>

void modifyContainer(name_record_set & ns)
{
  cout << endl << "ModifyContainer" << endl << "-------------" << endl;

  NameIndexType & idx1 = ns.get<NameIndex>();
  std::vector<IteratorType> v(
    boost::make_counting_iterator(idx1.begin()),
    boost::make_counting_iterator(idx1.end()));
  std::vector<IteratorType>::iterator it1=v.begin(),
                                      it2=v.end();

  while (it1 != it2)
  {
        cout<<(*it1)->get_name()<<endl;
        name_record nr = **it1;

        nr.setnew("_CHG");
        bool res = idx1.replace(*it1,nr);
        cout << "result is: " << res << endl;
        it1++;
  }
  cout << "--------------" << endl << endl;
}

如果您之前没有使用过它,则 make_counting_iterator 位只是填充向量的一种紧凑方式带有对 ns 的所有元素的迭代器。

while (it1 != it2)
{
      cout<<it1->get_name()<<endl;
      name_record nr = *it1;

      nr.setnew("_CHG");
      bool res = idx1.replace(it1,nr);
      cout << "result is: " << res << endl;
      it1++;
}

The problem with this code is that, once you've replaced an element x, this is automatically reordered to its new position, so that it1, which keeps pointing to x, "jumps" through the sequence and might skip or revisit elements.

The solution is to add a level of indirection and collect iterators to all the elements before beginning the replacements:

#include <vector>
#include <boost/iterator/counting_iterator.hpp>

void modifyContainer(name_record_set & ns)
{
  cout << endl << "ModifyContainer" << endl << "-------------" << endl;

  NameIndexType & idx1 = ns.get<NameIndex>();
  std::vector<IteratorType> v(
    boost::make_counting_iterator(idx1.begin()),
    boost::make_counting_iterator(idx1.end()));
  std::vector<IteratorType>::iterator it1=v.begin(),
                                      it2=v.end();

  while (it1 != it2)
  {
        cout<<(*it1)->get_name()<<endl;
        name_record nr = **it1;

        nr.setnew("_CHG");
        bool res = idx1.replace(*it1,nr);
        cout << "result is: " << res << endl;
        it1++;
  }
  cout << "--------------" << endl << endl;
}

In case you didn't use it before, the make_counting_iterator bit is just a compact way to populate the vector with iterators to all the elements of ns.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文