开发者

How to fill std::vector with data from another vector that meets some criteria

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.


http://www.boost.org/doc/libs/1_40_0/libs/iterator/doc/filter_iterator.html


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)>.


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;
}


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 );
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜