Hi, I have a vector of points, and I need to get those which are at a distance less than a value from a given point.
I could do it with a simple loop, but is there a better way to do it?
Thanks in advance
Hi, I have a vector of points, and I need to get those which are at a distance less than a value from a given point.
I could do it with a simple loop, but is there a better way to do it?
Thanks in advance
Use std::remove_copy_if
:
#include <algorithm>
#include <vector>
#include <iostream>
#include <functional>
#include <iterator>
int main() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(6);
v.push_back(10);
v.push_back(5);
v.push_back(2);
std::vector<int> v2;
std::remove_copy_if(v.begin(), v.end(), back_inserter(v2),
std::bind2nd(std::greater<int>(),5));
std::copy (v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout));
std::cout << std::endl;
return 0;
}
remove_copy_if
will copy a sequence to an output iterator for each item which fails a predicate. In this case, the predicate is "x>5". There doesn't seem to be an equivalent copy_if
for each item which passes a predicate test, but you can always negate a predicate with std::not1
.
as Philip and Beta suggest, here is a more general way, using a functor predicate. you could use C++0x lambdas instead of a handwriten functor.
#include <algorithm>
#include <vector>
#include <iostream>
#include <functional>
#include <iterator>
struct FunctorPredicate : public std::unary_function<bool,int>
{
bool operator(int i)
(
// do what you want here, in our case: test greater than 5.
return i > 5;
)
}
int main() {
std::vector<int> v;
v.push_back(3);
v.push_back(2);
v.push_back(6);
v.push_back(10);
v.push_back(5);
v.push_back(2);
std::vector<int> v2;
FunctorPredicate functorPredicate;
std::remove_copy_if(v.begin(), v.end(), back_inserter(v2),functorPredicate);
std::copy (v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout));
std::cout << std::endl;
return 0;
}
inheriting form std::unary_function defines the two following typedef: argument_type at int and result_type at bool.
and in Cplusplus STL reference for std::remove_copy_if there is another example with a simpler std::function<bool (int)>
.
Maxim proposed the boost::filter_iterator
already, but I suggest going one step further. The boost iterators alone are very cumbersome to use. Typically, you want to filter ranges, copy ranges, or search ranges. For every boost iterator, we have a utility function make_xxx_range like the following:
#include <boost/iterator/filter_iterator.hpp>
#include <boost/range/iterator_range.hpp>
template< class Range, class Pred >
boost::iterator_range< boost::filter_iterator< Pred, typename boost::range_iterator<Range>::type > >
make_filter_range( Range& rng, Pred p ) {
return boost::make_iterator_range( boost::make_filter_iterator(pred, boost::begin(rng), boost::end(rng)), boost::make_filter_iterator(pred, boost::end(rng), boost::end(rng)) );
}
Having that, the solution to your problem is trivial:
#include <boost/lambda/lambda.hpp>
int main() {
std::vector<int> v;
// fill vector
std::vector<int> v2 = boost::copy_range< std::vector<int> >(
make_filter_range( v, boost::lambda::_1 > 5 );
}
Sebastian proposed the boost::make_xxx_range
functions already, but I suggest going one step further. The boost::make_xxx_range alone are very cumbersome to use. Typically, you want to use boost::range ;)
#include <vector>
#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/range/algorithm_ext/push_back.hpp>
#include <boost/range/adaptor/filtered.hpp>
using namespace boost::adaptors;
using namespace boost::lambda;
int main()
{
std::vector<int> v = {3, 2, 6, 10, 5, 2};
std::vector<int> v2;
int dist = 5;
boost::push_back(v2, filter(v, _1 > dist));
boost::copy(v2, std::ostream_iterator<int>(std::cout, ","));
std::cout << std::endl;
return 0;
}