Boost logo

Boost Users :

From: Joaquin M Lopez Munoz (joaquin_at_[hidden])
Date: 2008-03-04 17:06:31


Hi Ovanes,

Ovanes Markarian <om_boost <at> keywallet.com> writes:

>
> Hello *,I currently need to implement the following use case
> and was wondering if this is possible with multi-index: I have
> a class, for simplicity all members are public wihtout accessors
> and mutators:
>
> class entry{
> public:
> field x;
> field y;
> field z;
> };
>
> I need a multi-index index to remember the order in which the
> elements were inserted and non uniquely index the inserted
> elements by hash of field x; Now a client could do the following
> queries:- get all entries in the order they were inserted
> (this is easy and I know how to do it)- get all entries which
> satisfy field x parameter in the order they were inserted.
> I know that I can retrieve the values dependent on hash(x), but
> these are probably not sorted. I know that I can project
> iterators, but can I project (range_retireved_via_hashed_X) to
> (range_retrieved_for_sequence_of_X)May be I miss smth here or
> should split my data in some other way to satisfy this condition.

As I see it, you've got two options here to get the elements with
equal x sorted by inclusion order:

1. Use an ordered index instead of (or additionally to) the hashed
index: elements with equal key are guaranteedly inserted in
insertion order.
2. Retrieve the range from the hashed index and sort it externally
according to the insertion order: here random_access indices
(http://tinyurl.com/2dvmul )come handy, as you can compare random
access iterators for order precedence. So, instead of a sequenced
index you'd have something like:

  typedef multi_index_container<
    entry,
    indexed_by<
      hashed_non_unique<member<entry,field,&entry::x> >,
      random_access<>
>
> multi_t;

and the range retrieval function could look like this:

  void range_as_inserted(const multi_t& m,field x)
  {
    typedef multi_t::nth_index_iterator<1>::type ra_iterator;
    typedef std::vector<ra_iterator> buffer;

    buffer buf;
    std::pair<multi_t::iterator,multi_t::iterator> p=m.equal_range(x);
    while(p.first!=p.second)buf.push_back(m.project<1>(p.first++));
    std::sort(buf.begin(),buf.end());
    for(buffer::iterator it=buf.begin(),it_end=buf.end();
        it!=it_end;++it){
      std::cout<<**it<<"\n";
    }
  }

The idea is: store the hash range as a vector of random access
iterators to the elements and then just std::sort it, using
the fact that a random_access iterator it0 is less than it1
(in our particular case) if it points to an older element (with
respecto to insertion time).

I can't attach files from Gmane, so please find the pasted code
of a complete snippet showing technique #2

Hope this helps,

Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo

-----------------BEGIN CODE-----------------
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/random_access_index.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/ref.hpp>
#include <algorithm>
#include <iostream>
#include <vector>

using namespace boost::multi_index;

typedef int field;
struct entry
{
  entry(int x,int y):x(x),y(y){}
  field x,y;
};

std::ostream& operator<<(std::ostream& out,const entry& e)
{
  return out<<e.x<<","<<e.y;
}

typedef multi_index_container<
  entry,
  indexed_by<
    hashed_non_unique<member<entry,field,&entry::x> >,
    random_access<>
>
> multi_t;

void range_as_inserted(const multi_t& m,field x)
{
  typedef multi_t::nth_index_iterator<1>::type ra_iterator;
  typedef std::vector<ra_iterator> buffer;

  buffer buf;
  std::pair<multi_t::iterator,multi_t::iterator> p=m.equal_range(x);
  while(p.first!=p.second)buf.push_back(m.project<1>(p.first++));
  std::sort(buf.begin(),buf.end());
  for(buffer::iterator it=buf.begin(),it_end=buf.end();it!=it_end;++it){
    std::cout<<**it<<"\n";
  }
}

int main()
{
  multi_t m;
  for(int i=0;i<60;++i)m.insert(entry(0,i));
  range_as_inserted(m,0);
}

-----------------END CODE-----------------


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net