transform

C

Chris Roth

I'm just starting out using the algorithms in c++ std library.

I have a vector of vectors (v) and want to get a slice at some index.
ex. If v held two vectors, v1 and v2:
v1 = 1 2 3 4 5 6
v2 = 7 7 8 8 9 9
the slice at position 3 would be 3 8 (v1(3) and v2(3)).

I think it is possible to use transform to make the slice matrix, but
I'm having trouble with the final argument:

vector< vector<double> > v;
// populate v

vector<double> slice;

transform( v.begin(), v.end(), slice.begin(), ??? );

What goes in ???
I have tried std::vector<double>::at(), but it didn't work.

Thanks c++ board.
 
J

John Carson

Chris Roth said:
I'm just starting out using the algorithms in c++ std library.

I have a vector of vectors (v) and want to get a slice at some index.
ex. If v held two vectors, v1 and v2:
v1 = 1 2 3 4 5 6
v2 = 7 7 8 8 9 9
the slice at position 3 would be 3 8 (v1(3) and v2(3)).

I think it is possible to use transform to make the slice matrix, but
I'm having trouble with the final argument:

vector< vector<double> > v;
// populate v

vector<double> slice;

transform( v.begin(), v.end(), slice.begin(), ??? );

What goes in ???
I have tried std::vector<double>::at(), but it didn't work.

Transform produces the same number of elements as output as there is input.
You want less elements as output.

What you call "position 3" is actually at index 2, so this will work:

for(int i=0; i<2; ++i)
slice.push_back(v[2]);
 
K

kwikius

I'm just starting out using the algorithms in c++ std library.

I have a vector of vectors (v) and want to get a slice at some index.
ex. If v held two vectors, v1 and v2:
v1 = 1 2 3 4 5 6
v2 = 7 7 8 8 9 9
the slice at position 3 would be 3 8 (v1(3) and v2(3)).

I think it is possible to use transform to make the slice matrix, but
I'm having trouble with the final argument:

vector< vector<double> > v;
// populate v

vector<double> slice;

transform( v.begin(), v.end(), slice.begin(), ??? );

What goes in ???
I have tried std::vector<double>::at(), but it didn't work.

Thanks c++ board.

FWIW heres my efforts. Some of the stuff is home brew stuff to set up
the containers and output results but underneath you should see the
std:: stuff poking out.

regards
Andy Little

#include <vector>
#include <algorithm>

// impl functors
// to do push_back and at
namespace impl_detail{

struct at_fun{
at_fun(int n_in) : n(n_in){}
int n;
template <typename C>
typename C::value_type
operator()(C & c) const
{
return c.at(n);
}

};

template <typename Fun, typename Container>
struct push_back_fun{
Container & c;
Fun const & f;
push_back_fun(Fun const & f_in,Container & c_in):f(f_in),c(c_in)
{}

template <typename T>
struct result{
typedef void type;
};
template <typename T>
typename result<T>::type
operator()(T const & t)const
{
return c.push_back(f(t));
}
};

}

// interface functions for push_back, at
inline
impl_detail::at_fun at( int n)
{
return impl_detail::at_fun(n);
};

template <typename F,typename Container>
inline
impl_detail::push_back_fun<F,Container> my_push_back(F const &
f,Container & c)
{
return impl_detail::push_back_fun<F,Container>(f,c);
}


//home brew stuff
#include <quan/fun/for_each.hpp>
#include <quan/fun/container_push_back.hpp>
#include <quan/fun/output.hpp>

int main()
{
// ---home brew impl stuff to populate the containers---
using quan::fun::for_each;
using quan::fun::push_back;
using quan::fun::eek:utput;
std::vector< std::vector<double> > v;
double ar1[] ={ 1, 2, 3, 4 ,5 ,6};
v.push_back(std::vector<double>());
for_each(ar1,push_back(v.back()));
double ar2[] = {7, 7 ,8 ,8 ,9 ,9 };
v.push_back(std::vector<double>());
for_each(ar2,push_back(v.back()));
//---end of home brew stuff---

std::vector< std::vector<double> > result;

// using std::for_each......
for (int i = 0; i != v[0].size(); ++i){
// add a vector to result
result.push_back(std::vector<double>());
// fill it
std::for_each(
v.begin(), v.end(),
my_push_back(at(i),result.at(i))
);

//more home brew to check it worked
for_each(result.at(i),output(std::cout," "));
std::cout << '\n';
}
}
 
C

Chris Theis

Chris Roth said:
I'm just starting out using the algorithms in c++ std library.

I have a vector of vectors (v) and want to get a slice at some index.
ex. If v held two vectors, v1 and v2:
v1 = 1 2 3 4 5 6
v2 = 7 7 8 8 9 9
the slice at position 3 would be 3 8 (v1(3) and v2(3)).

I think it is possible to use transform to make the slice matrix, but I'm
having trouble with the final argument:

vector< vector<double> > v;
// populate v

vector<double> slice;

transform( v.begin(), v.end(), slice.begin(), ??? );

What goes in ???
I have tried std::vector<double>::at(), but it didn't work.

Thanks c++ board.

You would actually need for_each with your own predicate and not transform.
However, IMHO using one of the generic algorithms supplied by the standard
library is a little overblown in that case. The slice you are referring to
is simply one columen of the matrix. So why not loop over all rows and
extract the value at the position you're looking for.

Something along the lines of the following (untested code!) should do the
trick:

for( vector<vector<double> >::iterator Iter = Matrix.begin(); Iter !=
Matrix.end(); ++Iter ) {
Slice.push_back( Iter->at(ColIndex) );
}

Cheers
Chris
 
?

=?ISO-8859-15?Q?Juli=E1n?= Albo

Chris said:
I'm just starting out using the algorithms in c++ std library.

I have a vector of vectors (v) and want to get a slice at some index.
ex. If v held two vectors, v1 and v2:
v1 = 1 2 3 4 5 6
v2 = 7 7 8 8 9 9
the slice at position 3 would be 3 8 (v1(3) and v2(3)).

I suppose you mean v1 [2] and v2 [2]

(...)
I have tried std::vector<double>::at(), but it didn't work.

at is overloaded, you must use some way to resolve ambiguity. This way
works:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <iterator>

using std::cout;
using std::vector;
using std::transform;
using std::bind2nd;
using std::mem_fun_ref;
using std::eek:stream_iterator;

int main ()
{
vector <vector <int> > v;
vector <int> a;
a.push_back (1); a.push_back (2); a.push_back (3);
a.push_back (4); a.push_back (5); a.push_back (6);
v.push_back (a);
a.clear ();
a.push_back (7); a.push_back (7); a.push_back (8);
a.push_back (8); a.push_back (9); a.push_back (9);
v.push_back (a);

int & (vector <int>::* const f) (size_t)= & vector <int>::at;
transform (v.begin (), v.end (),
ostream_iterator <int> (cout, " "),
bind2nd (mem_fun_ref (f), 2) );
cout << '\n';
}


// End of column.cpp
 
K

kwikius

FWIW heres my efforts. Some of the stuff is home brew stuff to set up
the containers and output results but underneath you should see the
std:: stuff poking out.

What the hey.. dump the std stuff and no more loop :)

#include <vector>
#include <quan/fun/for_each.hpp>
#include <quan/fun/container_reserve.hpp>
#include <quan/fun/container_push_back.hpp>
#include <quan/fun/output.hpp>
#include <quan/fun/std_at.hpp>

namespace quan { namespace fun{

//overload for_each to wrap integral iterator...
template <typename T, typename F>
typename boost::enable_if<
std::tr1::is_integral said:
for_each(T const & n, F const & f)
{
for (T i =0; i !=n; ++ i) {
f(i);
}
}

}}
//...so we can push for loop body into a functor...
namespace{
namespace impl{
template <typename In, typename Out>
struct apply{
apply( In & in_in, Out & out_in)
: in(in_in),out(out_in){}
In & in;
Out & out;
void operator()(size_t n) const
{
using quan::fun::for_each;
using quan::fun::push_back;
using quan::fun::eek:utput;
using quan::fun::std_at;

out.push_back(typename Out::value_type());
out.back().reserve(in.size());
for_each(in,push_back(std_at(n),out.at(n)));
for_each(out.at(n),output(std::cout," "));
std::cout << '\n';
}
};
}
template <typename In, typename Out>
impl::apply<In,Out> apply(In & in, Out & out)
{
return impl::apply<In,Out>(in,out);
}
}

int main()
{

using quan::fun::for_each;
using quan::fun::push_back;

std::vector< std::vector<double> > v(2);
for_each(v,quan::fun::reserve(6));

double ar1[] ={ 1, 2, 3, 4 ,5 ,6},
ar2[] = {7, 7 ,8 ,8 ,9 ,9 };

for_each(ar1,push_back(v[0]));
for_each(ar2,push_back(v[1]));

std::vector< std::vector<double> > result;
for_each(v[0].size(),apply(v,result));

}
/*
output:

1 7
2 7
3 8
4 8
5 9
6 9
*/
 
J

John Carson

John Carson said:
Transform produces the same number of elements as output as there is
input. You want less elements as output.

Oops. The number of elements here is two in each case, since you are
iterating over the two vector elements of the enclosing vector. Scratch that
comment.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,792
Messages
2,569,639
Members
45,348
Latest member
RoscoeNevi

Latest Threads

Top