|  | Initialize one vector using elements in second vector... |  | |
| | | Peter Seidler |  |
| Posted: Fri Aug 22, 2008 1:01 pm Post subject: Initialize one vector using elements in second vector... |  |
Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
-- Peter
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
On Aug 22, 3:01 pm, Peter Seidler <seidler@chem._INGEN_au_SPAM_.dk.sunsite.dk> wrote:
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
|
Your idea is basically sound, but you can't pass member functions this way. You need a binder, e.g. Boost.Bind or Std/TR1 bind.
#include <tr1/functional>
std::transform(idx.begin(), idx.end(), std::back_inserter(res), std::tr1::bind(&std::vector<int>::at, vec, _1));
This might not work with this exact syntax, because at() is overloaded on constness. It may have to look something like this: static_cast<const int& (std::vector<int>::*)(typename std::vector<int>::size_type) const>(&std::vector<int>::at) I don't know the syntax for "pointer to const member function", though.
Sebastian
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
|
std::transform(idx.begin(), idx.end(), std::back_inserter(res), elem_by_index(vec));
Where Im using a unaryfunction called elem_by_index that saves a reference to the backend vector, and simply returns the element specified by the index
struct elem_by_index { elem_by_index(std::vector<int> &v) : backend(v) {} int operator()(int index) const{ return backend[index]; }
private: std::vector<int> &backend; };
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Christian Hackl |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
Peter Seidler wrote:
| Quote: | Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); t |
You could accomplish it with the Boost Lambda Library. Here's an example:
typedef std::vector<int> Vector;
Vector::value_type const &(Vector::*at)(Vector::size_type) cons = &Vector::at;
std::transform(idx.begin(), idx.end(), std::back_inserter(res), bind(at, vec, _1));
The temporary variable "at" is used because the at() member function is overloaded for const and non-const. See LINK
-- Christian Hackl
[ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | JSoft |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
On Fri, 22 Aug 2008 07:01:51 -0600, Peter Seidler wrote:
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
|
What's wrong with this?
typeof idx::iterator it; typeof vec new_vec;
for (it = vec.begin(); it < vec.end(); ++it) new_vec.push_back(vec[*it]);
Jake
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | red floyd |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
On Aug 22, 6:01 am, Peter Seidler <seidler@chem._INGEN_au_SPAM_.dk.sunsite.dk> wrote:
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
|
How about something like:
struct converter { const std::vector<int>& v; converter(const std::vector<int>& v_) : v(v_) { } converter(const converter& c) : v(c.v) { } int operator()(int idx) const { return v.at(idx); } };
std::transform(idx.begin(), idx.end(), std::back_inserter(res), converter(vec));
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | uuilly |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
On Aug 22, 6:01 am, Peter Seidler <seidler@chem._INGEN_au_SPAM_.dk.sunsite.dk> wrote:
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
-- Peter
|
I always find that when you have to store indices, it's easiest to just use a traditional for loop. Esp w/ vector.
Otherwise, the only way I can think to do it would be to use boost::bind and the distance function acting on a reference from idx.at. While it could probably be done I think it will look pretty messy in the end. Though I would be keen on knowing an "STL way" of doing this.
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Guest |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
On Aug 22, 9:01 am, Peter Seidler <seidler@chem._INGEN_au_SPAM_.dk.sunsite.dk> wrote:
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
-- Peter
|
#include "boost/functional.hpp" // boost::mem_fun_ref
// tr1::...
transform( idx.begin( ), idx.end( ), res.begin( ), boost::bind1st( boost::mem_fun_ref< int&, vector< int, allocator<int> >, size_t
| Quote: | ( &vector< int, allocator<int> >::at ), vec ) ); |
//...
no boost:
//...
using namespace std;
template< typename From
| Quote: | struct select_element_of |
: public unary_function< const typename From::size_type&, void> {
explicit select_element_of( const From & from ) : from_( from ) { } operator const From ( ) { return result_; } void operator ()( const typename From::size_type & val ) { result_.push_back( from_[ val ] ); }
private: const From & from_; From result_; };
res = for_each( idx.begin( ), idx.end( ), select_element_of< vector< int > >( vec ) );
//...
cheers, gil
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | Greg Herlihy |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
On Aug 22, 6:01 am, Peter Seidler <seidler@chem._INGEN_au_SPAM_.dk.sunsite.dk> wrote:
| Quote: | I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
|
I think that you are on the right track. To complete the solution, I would suggest something along these lines:
#include <iostream> #include <iterator> #include <algorithm> #include <tr1/functional> #include <vector> #include <functional>
using std::tr1::placeholders::_1; using std::tr1::bind; using std::back_inserter; using std::tr1::mem_fn; using std::vector;
typedef vector<int> IntVector;
// declare an AtMemFunPtr member function pointer typedef // for std::vector<int>::at() const
typedef IntVector::const_reference (IntVector::*AtMemFunPtr)(IntVector::size_type) const;
const int va[] = { 10, 20, 30, 40, 50, 60 }; const int ia[] = { 2, 3, 5};
const int vaEnd = sizeof(va)/sizeof(va[0]); const int iaEnd = sizeof(ia)/sizeof(ia[0]);
int main() { IntVector values( &va[0], &va[vaEnd] ); IntVector indexes( &ia[0], &ia[iaEnd] );
IntVector v; // holds output
std::transform( indexes.begin(), indexes.end(), back_inserter(v), bind( AtMemFunPtr(&IntVector::at), values, _1));
std::cout << v[0] << "\n" << v[1] << "\n" << v[2] << "\n"; }
Program output:
30 40 60
Greg
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| | | gast128@hotmail.com |  |
| Posted: Sat Aug 23, 2008 11:58 pm Post subject: Re: Initialize one vector using elements in second vector... |  |
| |  | |
| Quote: | Hi, I have the following problem:
Given a vector: vec[10, 20, 30, 40, 50, 60] and another one: idx[ 2, 3, 5] I wish to generate a new vector based on the elements in vec given by the indices in idx, i.e. the result should be res[30, 40, 60].
Is there any way to accomplish this using the STL vectors / algorithms.
I would like to do something like: transform(idx.begin(), idx.end(), back_inserter(res), vec.at()); However this doesn't work.
Any suggestions?
|
It is quite simple if you are not afraid of boost (or tr1):
#include <algorithm> #include <iterator> #include <vector> #include <boost/bind.hpp> #include <boost/assign/list_of.hpp>
void f() { typedef std::vector<int> int_vector;
int_vector vec = boost::assign::list_of(10)(20)(30)(40)(50)(60); int_vector idx = boost::assign::list_of(2)(3)(5);
int_vector res;
std::transform(idx.begin(), idx.end(), std::back_inserter(res), boost::bind(&int_vector::at, &vec, _1)); }
-- [ See LINK for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |
| |
| Page 1 of 2 .:. Goto page 1, 2 Next | |
|
|