可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm trying to figure out the best way to determine whether I'm in the last iteration of a loop over a map in order to do something like the following:
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
}
}
There seem to be several ways of doing this: random access iterators, the distance
function, etc. What's the canonical method?
Edit: no random access iterators for maps!
回答1:
Canonical? I can't claim that, but I'd suggest
final_iter = someMap.end();
--final_iter;
if (iter != final_iter) ...
Edited to correct as suggested by KTC. (Thanks! Sometimes you go too quick and mess up on the simplest things...)
回答2:
Since C++11, you can also use std::next()
for (auto iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (std::next(iter) != someMap.end()) {
// do something for all but the last iteration
}
}
Although the question was asked a while ago, I thought it would be worth sharing.
回答3:
This seems like the simplest:
bool last_iteration = iter == (--someMap.end());
回答4:
If you just want to use a ForwardIterator, this should work:
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
}
}
回答5:
Modified Mark Ransom's so it actually work as intended.
finalIter = someMap.end();
--finalIter;
if (iter != final_iter)
回答6:
Surprised no one mentioned it yet, but of course boost has something ;)
Boost.Next (and the equivalent Boost.Prior)
Your example would look like:
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
}
}
回答7:
The following code would be optimized by a compiler so that to be the best solution for this task by performance as well as by OOP rules:
if (&*it == &*someMap.rbegin()) {
//the last iteration
}
This is the best code by OOP rules because std::map has got a special member function rbegin for the code like:
final_iter = someMap.end();
--final_iter;
回答8:
#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 ) );
}
Using std::for_each will ensure that the loop is tight and accurate... Note the introduction of the function foo() which takes a single argument (the type should match what is contained in someMap). This approach has the added addition of being 1 line. Of course, if Foo is really small, you can use a lambda function and get rid of the call to &Foo.
回答9:
Why to work to find the EOF so that you dont give something to it.
Simply, exclude it;
for (iter = someMap.begin(); someMap.end() - 1; ++iter) {
//apply to all from begin to second last element
}
KISS (KEEP IT SIMPLY SIMPLE)
回答10:
A simple, yet effective, approach:
size_t items_remaining = someMap.size();
for (iter = someMap.begin(); iter != someMap.end(); iter++) {
bool last_iteration = items_remaining-- == 1;
}
回答11:
Here's my optimized take:
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);
回答12:
How about this, no one mentioning but...
for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
// do something for all iterations
if (iter != --someMap.end()) {
// do something for all but the last iteration
}
}
this seems simple, mm...
回答13:
Full program:
#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;
}
This program yields:
1 2 3 4 5 | last: 6
回答14:
You can just pull an element out of the map prior to iteration, then perform your "last iteration" work out of the loop and then put the element back into the map. This is horribly bad for asynchronous code, but considering how bad the rest of C++ is for concurrency, I don't think it'll be an issue. :-)