C++ 使用 STL 查找向量中的所有元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/234482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
using STL to find all elements in a vector
提问by twokats
I have a collection of elements that I need to operate over, calling member functions on the collection:
我有一个需要操作的元素集合,在集合上调用成员函数:
std::vector<MyType> v;
... // vector is populated
For calling functions with no arguments it's pretty straight-forward:
对于不带参数的调用函数,它非常简单:
std::for_each(v.begin(), v.end(), std::mem_fun(&MyType::myfunc));
A similar thing can be done if there's one argument to the function I wish to call.
如果我希望调用的函数有一个参数,则可以完成类似的操作。
My problem is that I want to call a function on elements in the vector if it meets some condition. std::find_if
returns an iterator to the first element meeting the conditions of the predicate.
我的问题是,如果满足某个条件,我想对向量中的元素调用函数。 std::find_if
返回第一个满足谓词条件的元素的迭代器。
std::vector<MyType>::iterator it =
std::find_if(v.begin(), v.end(), MyPred());
I wish to find allelements meeting the predicate and operate over them.
我希望找到满足谓词的所有元素并对其进行操作。
I've been looking at the STL algorithms for a "find_all
" or "do_if
" equivalent, or a way I can do this with the existing STL (such that I only need to iterate once), rather than rolling my own or simply do a standard iteration using a for loop and comparisons.
我一直在寻找“ find_all
”或“ do_if
”等价物的 STL 算法,或者我可以使用现有 STL 执行此操作的方法(这样我只需要迭代一次),而不是滚动我自己的或简单地执行标准使用 for 循环和比较进行迭代。
回答by paxos1977
Boost Lambda makes this easy.
Boost Lambda 让这一切变得简单。
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>
std::for_each( v.begin(), v.end(),
if_( MyPred() )[ std::mem_fun(&MyType::myfunc) ]
);
You could even do away with defining MyPred(), if it is simple. This is where lambda really shines. E.g., if MyPred meant "is divisible by 2":
如果很简单,您甚至可以取消定义 MyPred()。这就是 lambda 真正闪耀的地方。例如,如果 MyPred 的意思是“可被 2 整除”:
std::for_each( v.begin(), v.end(),
if_( _1 % 2 == 0 )[ std::mem_fun( &MyType::myfunc ) ]
);
Update:更新:使用 C++0x lambda 语法执行此操作也非常好(继续将谓词作为模 2):
std::for_each( v.begin(), v.end(),
[](MyType& mt ) mutable
{
if( mt % 2 == 0)
{
mt.myfunc();
}
} );
At first glance this looks like a step backwards from boost::lambda syntax, however, it is better because more complex functor logic is trivial to implement with c++0x syntax... where anything very complicated in boost::lambda gets tricky quickly. Microsoft Visual Studio 2010 beta 2 currently implements this functionality.
乍一看,这看起来像是从 boost::lambda 语法倒退了一步,但是,它更好,因为使用 c++0x 语法实现更复杂的函子逻辑是微不足道的......boost::lambda 中任何非常复杂的东西都会变得棘手迅速地。Microsoft Visual Studio 2010 beta 2 当前实现了此功能。
回答by John Dibling
I wrote a for_each_if()
and a for_each_equal()
which do what I think you're looking for.
我写了 afor_each_if()
和 afor_each_equal()
做我认为你正在寻找的东西。
for_each_if()
takes a predicate functor to evaluate equality, and for_each_equal()
takes a value of any type and does a direct comparison using operator ==
. In both cases, the function you pass in is called on each element that passes the equality test.
for_each_if()
采用谓词函子来评估相等性,并for_each_equal()
采用任何类型的值并使用 进行直接比较operator ==
。在这两种情况下,您传入的函数都会在通过相等性测试的每个元素上调用。
/* ---
For each
25.1.1
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f)
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f)
Requires:
T is of type EqualityComparable (20.1.1)
Effects:
Applies f to each dereferenced iterator i in the range [first, last) where one of the following conditions hold:
1: *i == value
2: pred(*i) != false
Returns:
f
Complexity:
At most last - first applications of f
--- */
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first,
InputIterator last,
Predicate pred,
Function f)
{
for( ; first != last; ++first)
{
if( pred(*first) )
f(*first);
}
return f;
};
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first,
InputIterator last,
const T& value,
Function f)
{
for( ; first != last; ++first)
{
if( *first == value )
f(*first);
}
return f;
};
回答by Marcin
Is it ok to change the vector? You may want to look at the partition algorithm.
Partition algorithm
可以改变向量吗?您可能想查看分区算法。
分区算法
Another option would be to change your MyType::myfunc
to either check the element, or to take a predicate as a parameter and use it to test the element it's operating on.
另一种选择是将您更改MyType::myfunc
为检查元素,或者将谓词作为参数并使用它来测试它正在操作的元素。
回答by Max Lybbert
std::vector<int> v, matches;
std::vector<int>::iterator i = v.begin();
MyPred my_pred;
while(true) {
i = std::find_if(i, v.end(), my_pred);
if (i == v.end())
break;
matches.push_back(*i);
}
For the record, while I have seen an implementation where calling end()
on a list
was O(n), I haven't seen any STL implementations where calling end()
on a vector
was anything other than O(1) -- mainly because vector
s are guaranteed to have random-access iterators.
作为记录,虽然我见过调用end()
alist
是 O(n) 的实现,但我还没有看到调用end()
avector
不是 O(1) 的任何 STL 实现——主要是因为vector
s 保证具有随机-访问迭代器。
Even so, if you are worried about an inefficient end()
, you can use this code:
即便如此,如果您担心效率低下end()
,您可以使用以下代码:
std::vector<int> v, matches;
std::vector<int>::iterator i = v.begin(), end = v.end();
MyPred my_pred;
while(true) {
i = std::find_if(i, v.end(), my_pred);
if (i == end)
break;
matches.push_back(*i);
}
回答by computinglife
回答by Ferruccio
You can use Boost.Foreach:
您可以使用Boost.Foreach:
BOOST_FOREACH (vector<...>& x, v)
{
if (Check(x)
DoStuff(x);
}
回答by Greg Rogers
For what its worth for_each_ifis being considered as an eventual addition to boost. It isn't hard to implement your own.
for_each_if的价值被认为是对 boost 的最终补充。实现自己的并不难。