[multi_index] Sorting object based on some specified criteria !!

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

[multi_index] Sorting object based on some specified criteria !!

Patel Priyank-PPATEL1
Hi all,
 
I have following kind of class and having some identifier and group id associated with
particular procedure. I want to know if I have to get the procedures relating particular
group for ex. (groupId == 1). How do I do using multiindex container? Can somebody
please give me some hint or code if they have done something similar to what I want
to do?
 
Thanks a lot,
Priyank
 
 
// class procedure test
class Procedure {
public:
 Procedure(int _id, int _group ) : id_(_id), group_(_group) {
 }
 int get_id() const {
  return id_;
 }
int get_group() const {
return group_;
}
 friend ostream& operator << (ostream& _os, const Procedure& _proc);
 
private:
 int id_;
int group_;
};
 
ostream& operator << (ostream& _os, const Procedure& _proc)
{
 _os << "PROCEDURE : " << _proc.id_ << endl;
 return _os;
}
 
// Defines multiindex container that is hashed based on id
struct id {
};
 
typedef multi_index_container<
Procedure*,
indexed_by<
hashed_unique<
tag<id>, const_mem_fun<Procedure, int, &Procedure::get_id> >
>
> Procedure_Hashed_Pool;
 
typedef Procedure_Hashed_Pool::index<id>::type Procedure_By_Id;
 
 

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [multi_index] Sorting object based on some specified criteria !!

Joaquin M LópezMuñoz
Patel Priyank-PPATEL1 <priyankpatel <at> motorola.com> writes:

>
>
> Hi
> all,
>
>  
> I have following
> kind of class and having some identifier and group id associated
> with
> particular
> procedure. I want to know if I have to get the procedures relating particular
>
> group for ex.
> (groupId == 1). How do I do using multiindex container? Can
> somebody
> please give me some
> hint or code if they have done something similar to what I
> want
> to do?
>

Hello Priyank, I'm not sure I've understood what you're after,
but let me try anyway:

As you'll search for group, you'll need an additional index
(the one you've set up is based on process ID). The following
has not been compiled, beware typos:


  struct id {};
  struct group {};
 
  typedef
  multi_index_container<
    Procedure*,
    indexed_by<
      hashed_unique<
       tag<id>,
       const_mem_fun<Procedure, int, &Procedure::get_id> >
      >,
      hashed_non_unique<
       tag<group>,
       const_mem_fun<Procedure, int, &Procedure::get_group> >
      >
    >
  >
  Procedure_Hashed_Pool;
 
  typedef Procedure_Hashed_Pool::
    index<id>::type               Procedure_By_Id;
  typedef Procedure_Hashed_Pool::
    index<group>::type            Procedure_By_Group;

(I've decided to make the new index hashed non-unique,
you could also have it ordered non-unique if you need
the elements to be sorted by group ID --hashing only
guarantees fast retrieval.)
And now you can simply use equal_range() on this index
to do what you want:

  int gr=...;
  const Procedure_By_Group& procedure_bg=
    procedure_pool.get<group>();
  std::pair<
    Procedure_By_Group::iterator,
    Procedure_By_Group::iterator
  > p=procedure_bg.equal_range(gr);

p will hold the range of elements with group ID == gr.

Is this what you were after?

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

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [multi_index] Sorting object based on some specified criteria !!

Patel Priyank-PPATEL1
In reply to this post by Patel Priyank-PPATEL1
Hi Joaquin,

First of all thanks for your time and response. I have it working as follows, but seems I have to recalculate iterators if in case I later on modify group associated with that access point. Is there any way that iterators will know automatically update when I update access point in future to some other group?
Let me know if you have come across that one. I am going to look in your code in detail and get back to you in case of any questions.

Thanks
Priyank

// class Access point test
class Access_Point {
public:
        Access_Point(int id, int paging_group):id_(id), pg_(paging_group) {
        }
        bool by_id(int _id) const {
                return (_id == id_);
        }
        int paging_group(int _pg) const {
                return (_pg == pg_);
        }
        int id() const {
                return id_;
        }
        int pg() const {
                return pg_;
        }
        int pg(int _pg) {
                pg_ = _pg;
        }
        friend ostream& operator << (ostream& _os, const Access_Point& _ap);
private:
        int id_;
        int pg_;
};
ostream& operator << (ostream& _os, const Access_Point& _ap)
{
        _os << "Id: " << _ap.id_ << "Pg: " << _ap.pg_ << endl;
        return _os;
}

// tag ids
struct hashed_objs {
};
struct paging_group {
};

// Create multi index container

typedef multi_index_container<
Access_Point*,
indexed_by<

hashed_unique<
tag<hashed_objs>, const_mem_fun<Access_Point, int, &Access_Point::id> >,

ordered_non_unique <
tag<paging_group>, const_mem_fun<Access_Point, int, &Access_Point::pg>
>

>
> Access_Points;
 
int ACE_MAIN (int, ACE_TCHAR *[])
{
// ACCESS POINT CHECK
        Access_Points pool;
        Access_Point * a1 = new Access_Point(1, 1);
        Access_Point * a2 = new Access_Point(2, 1);
        Access_Point * a3 = new Access_Point(3, 2);
        Access_Point * a4 = new Access_Point(4, 1);
        // insert all the access points
        pool.insert(a1);
        pool.insert(a2);
        pool.insert(a3);
        // get iterator
        index_iterator<Access_Points, paging_group>::type pg0, pg1;
        boost::tuples::tie(pg0, pg1) = get<paging_group> (pool).equal_range(1);
        pool.insert(a4);
        // print all that is there
        while (pg0 != pg1) {
                cout << *(*pg0) << endl;
                pg0++;
        }

        // change paging group from access point 4
        a4->pg(2);
        // NEED TO RECALCULATE ITERATORS
        boost::tuples::tie(pg0, pg1) = get<paging_group> (pool).equal_range(1);
        while (pg0 != pg1) {
                cout << *(*pg0) << endl;
                pg0++;
        }
        // return success
        return 0;
}




















-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Joaquin M Lopez Munoz
Sent: Monday, April 17, 2006 2:26 PM
To: [hidden email]
Subject: Re: [Boost-users][multi_index] Sorting object based on some specified criteria !!

Patel Priyank-PPATEL1 <priyankpatel <at> motorola.com> writes:

>
>
> Hi
> all,
>
>  
> I have following
> kind of class and having some identifier and group id associated with
> particular procedure. I want to know if I have to get the procedures
> relating particular
>
> group for ex.
> (groupId == 1). How do I do using multiindex container? Can somebody
> please give me some hint or code if they have done something similar
> to what I want to do?
>

Hello Priyank, I'm not sure I've understood what you're after, but let me try anyway:

As you'll search for group, you'll need an additional index (the one you've set up is based on process ID). The following has not been compiled, beware typos:


  struct id {};
  struct group {};
 
  typedef
  multi_index_container<
    Procedure*,
    indexed_by<
      hashed_unique<
       tag<id>,
       const_mem_fun<Procedure, int, &Procedure::get_id> >
      >,
      hashed_non_unique<
       tag<group>,
       const_mem_fun<Procedure, int, &Procedure::get_group> >
      >
    >
  >
  Procedure_Hashed_Pool;
 
  typedef Procedure_Hashed_Pool::
    index<id>::type               Procedure_By_Id;
  typedef Procedure_Hashed_Pool::
    index<group>::type            Procedure_By_Group;

(I've decided to make the new index hashed non-unique, you could also have it ordered non-unique if you need the elements to be sorted by group ID --hashing only guarantees fast retrieval.) And now you can simply use equal_range() on this index to do what you want:

  int gr=...;
  const Procedure_By_Group& procedure_bg=
    procedure_pool.get<group>();
  std::pair<
    Procedure_By_Group::iterator,
    Procedure_By_Group::iterator
  > p=procedure_bg.equal_range(gr);

p will hold the range of elements with group ID == gr.

Is this what you were after?

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

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [multi_index] Sorting object based on some specified criteria!!

Joaquin M LópezMuñoz
Patel Priyank-PPATEL1 ha escrito:

> Hi Joaquin,
>
> First of all thanks for your time and response. I have it working as follows, but seems I have to recalculate iterators if in case I later on modify group associated with that access point. Is there any way that iterators will know automatically update when I update access point in future to some other group?
> Let me know if you have come across that one. I am going to look in your code in detail and get back to you in case of any questions.

Hello Priyank, there's  an issue in your code:

>         // change paging group from access point 4
>         a4->pg(2);

This is incorrect and can lead to hard-to-detect failures later on during the execution
of the program: basically, you're changing an element key "under the table", that is,
without the multi-index container having a chance to notice, which directly
breaks the internal invariants the container relies on. Under usual conditions it
is difficult to change a key in such a way, because the elements of a multi-index
container are treated as const, but here you can easily get by because it is
pointers that you are storing.
The proper way to modify an element is by using replace, modify of modify_key,
as explained in

http://boost.org/libs/multi_index/doc/tutorial.html#ord_updating

In your case, instead of what you've got you could write the following:

  // get an iterator to a4. You could also have stored those iterators in the
  // first place when inserting the elements.

  Access_Points::iterator it=pool.find(4);

  // change paging group from access point 4
  pool.modify(it,boost::bind(&Access_point::pg,_1,2));

By using modify(), the multi-index container is on control of the updating
operation, and will rearrange a4 according to its new paging group.

>         // NEED TO RECALCULATE ITERATORS
>         boost::tuples::tie(pg0, pg1) = get<paging_group> (pool).equal_range(1);

As for your original question, yes, you've got to recalculate these iterators in
the general case, as elements might have been moved around, inserted or
deleted: for instance, if the element originally pointed to by pg0 had been
deleted, pg0 would not even be valid after that.

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

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
Reply | Threaded
Open this post in threaded view
|

Re: [multi_index] Sorting object based on some specified criteria!!

Patel Priyank-PPATEL1
Hi Joaquin,

Thanks for all your replies. Let me read carefully the link you sent out.
I will write you back in case of any more questions. Thanks for this great library,
it is really helpful.

Thanks again,
Priyank
 

-----Original Message-----
From: [hidden email] [mailto:[hidden email]] On Behalf Of Joaquín Mª López Muñoz
Sent: Tuesday, April 18, 2006 2:21 AM
To: [hidden email]
Subject: Re: [Boost-users] [multi_index] Sorting object based on some specified criteria!!

Patel Priyank-PPATEL1 ha escrito:

> Hi Joaquin,
>
> First of all thanks for your time and response. I have it working as follows, but seems I have to recalculate iterators if in case I later on modify group associated with that access point. Is there any way that iterators will know automatically update when I update access point in future to some other group?
> Let me know if you have come across that one. I am going to look in your code in detail and get back to you in case of any questions.

Hello Priyank, there's  an issue in your code:

>         // change paging group from access point 4
>         a4->pg(2);

This is incorrect and can lead to hard-to-detect failures later on during the execution of the program: basically, you're changing an element key "under the table", that is, without the multi-index container having a chance to notice, which directly breaks the internal invariants the container relies on. Under usual conditions it is difficult to change a key in such a way, because the elements of a multi-index container are treated as const, but here you can easily get by because it is pointers that you are storing.
The proper way to modify an element is by using replace, modify of modify_key, as explained in

http://boost.org/libs/multi_index/doc/tutorial.html#ord_updating

In your case, instead of what you've got you could write the following:

  // get an iterator to a4. You could also have stored those iterators in the
  // first place when inserting the elements.

  Access_Points::iterator it=pool.find(4);

  // change paging group from access point 4
  pool.modify(it,boost::bind(&Access_point::pg,_1,2));

By using modify(), the multi-index container is on control of the updating operation, and will rearrange a4 according to its new paging group.

>         // NEED TO RECALCULATE ITERATORS
>         boost::tuples::tie(pg0, pg1) = get<paging_group>
> (pool).equal_range(1);

As for your original question, yes, you've got to recalculate these iterators in the general case, as elements might have been moved around, inserted or
deleted: for instance, if the element originally pointed to by pg0 had been deleted, pg0 would not even be valid after that.

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

_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users
_______________________________________________
Boost-users mailing list
[hidden email]
http://lists.boost.org/mailman/listinfo.cgi/boost-users