如何在std :: map的循环中检测到最后一次迭代?
时间:2020-03-06 14:54:02 来源:igfitidea点击:
我正在尝试找出确定自己是否在地图循环的最后迭代中的最佳方法,以便执行以下操作:
for (iter = someMap.begin(); iter != someMap.end(); ++iter) { bool last_iteration; // do something for all iterations if (!last_iteration) { // do something for all but the last iteration } }
似乎有几种方法可以做到这一点:随机访问迭代器,"距离"函数等。规范方法是什么?
编辑:没有用于地图的随机访问迭代器!
解决方案
这似乎是最简单的:
bool last_iteration = iter == (--someMap.end());
我们可以仅在迭代之前将元素从地图中拉出,然后从循环中执行"最后一次迭代"工作,然后将元素放回地图中。对于异步代码来说,这是非常糟糕的,但是考虑到其余C ++对于并发的严重性,我认为这不会成为问题。 :-)
典范?我不能这么说,但我建议
final_iter = someMap.end(); --final_iter; if (iter != final_iter) ...
根据KTC的建议进行编辑以更正。 (谢谢!有时我们走得太快,弄乱了最简单的事情……)
修改了Mark Ransom,使其实际上按预期工作。
finalIter = someMap.end(); --finalIter; if (iter != final_iter)
一种简单但有效的方法:
size_t items_remaining = someMap.size(); for (iter = someMap.begin(); iter != someMap.end(); iter++) { bool last_iteration = items_remaining-- == 1; }
完整程序:
#include <iostream> #include <list> void process(int ii) { std::cout << " " << ii; } int main(void) { std::list<int> ll; ll.push_back(1); ll.push_back(2); ll.push_back(3); ll.push_back(4); ll.push_back(5); ll.push_back(6); std::list<int>::iterator iter = ll.begin(); if (iter != ll.end()) { std::list<int>::iterator lastIter = iter; ++ iter; while (iter != ll.end()) { process(*lastIter); lastIter = iter; ++ iter; } // todo: think if you need to process *lastIter std::cout << " | last:"; process(*lastIter); } std::cout << std::endl; return 0; }
该程序产生:
1 2 3 4 5 | last: 6
#include <boost/lambda/lambda.hpp> #include <boost/lambda/bind.hpp> #include <algorithm> using namespace boost::lambda; // call the function foo on each element but the last... if( !someMap.empty() ) { std::for_each( someMap.begin(), --someMap.end(), bind( &Foo, _1 ) ); }
使用std :: for_each将确保循环紧密且准确...请注意引入了带有单个参数的foo()函数(类型应与someMap所包含的匹配)。这种方法增加了1行。当然,如果Foo很小,则可以使用lambda函数并摆脱对&Foo的调用。
如果我们只想使用ForwardIterator,则应该可以使用:
for ( i = c.begin(); i != c.end(); ) { iterator cur = i++; // do something, using cur if ( i != c.end() ) { // do something using cur for all but the last iteration } }
这是我的最佳选择:
iter = someMap.begin(); do { // Note that curr = iter++ may involve up to three copy operations curr = iter; // Do stuff with curr if (++iter == someMap.end()) { // Oh, this was the last iteration break; } // Do more stuff with curr } while (true);
还没有人感到惊讶,但是boost当然有一些特色;)
Boost.Next(和等效的Boost.Prior)
示例如下所示:
for (iter = someMap.begin(); iter != someMap.end(); ++iter) { // do something for all iterations if (boost::next(iter) != someMap.end()) { // do something for all but the last iteration } }