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
提前致谢
5 个解决方案
#1
10
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
.
remove_copy_if会将序列复制到每个未通过谓词的项的输出迭代器。在这种情况下,谓词是“x> 5”。对于通过谓词测试的每个项目,似乎没有等效的copy_if,但是您总是可以使用std :: not1来否定谓词。
#3
4
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.
正如Philip和Beta所暗示的,这是一种更通用的方法,使用仿函数谓词。你可以使用C ++ 0x lambdas而不是handwriten仿函数。
#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.
继承形式std :: unary_function定义了以下两个typedef:int的argument_type和bool的result_type。
and in Cplusplus STL reference for std::remove_copy_if there is another example with a simpler std::function<bool (int)>
.
在std :: remove_copy_if的Cplusplus STL参考中,还有另一个更简单的std :: function
#4
2
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 ;)
塞巴斯蒂安已经提出了boost :: make_xxx_range函数,但我建议更进一步。仅使用boost :: make_xxx_range非常麻烦。通常,你想使用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;
}
#5
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:
Maxim已经提出了boost :: filter_iterator,但我建议更进一步。单独使用增强迭代器非常麻烦。通常,您希望过滤范围,复制范围或搜索范围。对于每个boost迭代器,我们都有一个实用函数make_xxx_range,如下所示:
#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 );
}
#1
10
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
.
remove_copy_if会将序列复制到每个未通过谓词的项的输出迭代器。在这种情况下,谓词是“x> 5”。对于通过谓词测试的每个项目,似乎没有等效的copy_if,但是您总是可以使用std :: not1来否定谓词。
#2
#3
4
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.
正如Philip和Beta所暗示的,这是一种更通用的方法,使用仿函数谓词。你可以使用C ++ 0x lambdas而不是handwriten仿函数。
#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.
继承形式std :: unary_function定义了以下两个typedef:int的argument_type和bool的result_type。
and in Cplusplus STL reference for std::remove_copy_if there is another example with a simpler std::function<bool (int)>
.
在std :: remove_copy_if的Cplusplus STL参考中,还有另一个更简单的std :: function
#4
2
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 ;)
塞巴斯蒂安已经提出了boost :: make_xxx_range函数,但我建议更进一步。仅使用boost :: make_xxx_range非常麻烦。通常,你想使用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;
}
#5
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:
Maxim已经提出了boost :: filter_iterator,但我建议更进一步。单独使用增强迭代器非常麻烦。通常,您希望过滤范围,复制范围或搜索范围。对于每个boost迭代器,我们都有一个实用函数make_xxx_range,如下所示:
#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 );
}