使用STL查找向量中的所有元素
我有一个需要操作的元素集合,调用集合上的成员函数:
std::vector<MyType> v;
... // vector is populated
对于调用不带参数的函数,这非常简单:
std::for_each(v.begin(), v.end(), std::mem_fun(&MyType::myfunc));
如果我希望调用的函数有一个参数,则可以完成类似的操作。
我的问题是,如果满足某些条件,我想对向量中的元素调用函数。 std::find_if
返回一个迭代器,指向满足谓词条件的第一个元素。
std::vector<MyType>::iterator it =
std::find_if(v.begin(), v.end(), MyPred());
我希望找到满足谓词的所有元素并对其进行操作。
我一直在研究“find_all
”或“do_if
”等价物的STL算法,或者我可以用现有的STL来做到这一点的方法(这样我只需要迭代一次),而不是自己滚动或简单地使用 for 循环和比较进行标准迭代。
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::vector<MyType>::iterator it =
std::find_if(v.begin(), v.end(), MyPred());
I wish to find all elements 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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
Boost Lambda 让这一切变得简单。
如果很简单,您甚至可以取消定义 MyPred()。 这就是 lambda 真正发挥作用的地方。 例如,如果 MyPred 的意思是“可被 2 整除”:
Update:
Doing this with the C++0x lambda syntax is also very nice (continuing with the predicate as modulo 2):
乍一看,这看起来像是从 boost::lambda 语法倒退了一步,但是,它更好,因为使用 c++0x 语法实现更复杂的函子逻辑是微不足道的……在 boost::lambda 中任何非常复杂的东西都会变得棘手迅速地。 Microsoft Visual Studio 2010 beta 2 目前实现了此功能。
Boost Lambda makes this easy.
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":
Update:
Doing this with the C++0x lambda syntax is also very nice (continuing with the predicate as modulo 2):
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.
我编写了一个
for_each_if()
和一个for_each_equal()
,它们可以实现我认为您正在寻找的功能。for_each_if()
采用谓词函子来评估相等性,for_each_equal()
采用任何类型的值并使用operator ==
进行直接比较>。 在这两种情况下,都会在每个通过相等性测试的元素上调用您传入的函数。I wrote a
for_each_if()
and afor_each_equal()
which do what I think you're looking for.for_each_if()
takes a predicate functor to evaluate equality, andfor_each_equal()
takes a value of any type and does a direct comparison usingoperator ==
. In both cases, the function you pass in is called on each element that passes the equality test.改变向量可以吗? 您可能想查看分区算法。
分区算法
另一种选择是更改您的
MyType::myfunc
检查元素,或者将谓词作为参数并使用它来测试正在操作的元素。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.郑重声明,虽然我见过在
list
上调用end()
的实现时间复杂度为 O(n),但我还没有看到任何调用end()
的 STL 实现vector
上的 >end() 不是 O(1) - 主要是因为vector
保证具有随机访问迭代器。即便如此,如果您担心
end()
效率低下,您可以使用以下代码:For the record, while I have seen an implementation where calling
end()
on alist
was O(n), I haven't seen any STL implementations where callingend()
on avector
was anything other than O(1) -- mainly becausevector
s are guaranteed to have random-access iterators.Even so, if you are worried about an inefficient
end()
, you can use this code:对于其价值 for_each_if 被视为最终增加提升。 实现你自己的并不难。
For what its worth for_each_if is being considered as an eventual addition to boost. It isn't hard to implement your own.
Lamda 函数 - 想法是做这样的事情
这里 。
Lamda functions - the idea is to do something like this
Origial post here.
您可以使用 Boost.Foreach:
You can use Boost.Foreach: