Looping on C++ iterators starting with second (or nth) item
I am looking for a readable, elegant way to do the following in C++, here shown in Python:
for datum in data[1:]:
# do work.
The iterators on the data in question may not support random access iterators, so I can't just use:
for (mIter = data.begin() + 1; mIter != data.end(); mIter++)
The best I've come up with is the following:
iterable::iterator mIter = data.begin();
for (mIter++; mIter != allMjds.end(); mjdIter++) {
// do work.
}
It's not too lengthy, but it'开发者_如何转开发s hardly expository - at first glance it actually looks like a mistake!
Another solution is to have an "nth element" helper function, I guess. Is there a more concise way?
You can use std::next(iter, n)
for a linear-time advance. You can also use the standard std::advance
algorithm, though it isn't as simple to use (it takes the iterator by a non-const reference and doesn't return it).
For example,
for (mIter = std::next(data.begin()); mIter != data.end(); ++mIter)
or,
mIter = data.begin();
std::advance(mIter, 1);
for (; mIter != data.end(); ++mIter)
Note that you must make sure that data.size() >= 1
, otherwise the code will fail in a catastrophic manner.
#include <iterator>
iterator iter = data.begin();
for (advance(iter, 1); iter != data.end(); ++iter)
{
// do work
}
This relies on >= 1 element in data
to avoid an exception, though.
You could try:
for (mIter = data.begin() ; ++mIter != data.end() ; )
but you'd need to make sure that if data.begin () == data.end ()
doing the ++mIter
doesn't cause a problem.
Since this is a non-standard for loop, using a while loop might be more appropriate as there are fewer preconceived ideas about how they work, i.e. people looking at your code are more likely to read a while statement than a for statement as there is usually a model of how a for loop should work in their head.
mIter = data.begin ();
while (++mIter != data.end ())
{
}
You can use boost::next for this (but you should be sure that the list actually has an element in it before doing so):
#include <algorithm>
#include <iostream>
#include <iterator>
#include <list>
#include <boost/assign.hpp>
#include <boost/next_prior.hpp>
using namespace boost::assign;
int main()
{
std::list<int> lst = list_of(23)(9)(84)(24)(12)(18);
std::copy(boost::next(lst.begin()), lst.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
iterable::iterator mIter = data.begin();
std::for_each(++mIter, data.end(), some_func);
where some_func
contains the code you want to execute... you could even trivialise it with a simple wrapper function
template <typename _cont, typename _func>
for_1_to_end(_cont const& container, some_func func)
{
typename _cont::const_iterator it = _cont.begin();
std::for_each(++it, _cont.end(), func);
}
This is how i would do it
// starting position in the list
int i = 4;
// initialize "it" to point to the first item of data.
std::list<int>::iterator it = data_list.begin();
if (i < data.size()) {
// loop starting from 4 to end of the list.
for (std::advance(it, i); it != token_list.end(); it++) {
//use "it" here
}
}
else {
// Error: starting point is greater than size of data
}
What might be a good solution in a modern c++ way :
std::for_each(cbegin(data)+1,cend(data),[&](const auto& elem)
{
//do whatever you want with elem here
});
This will work even if data
is empty. It's basically possible to use this in the exact same way as you would do it with a standard for-range loop and has the advantage not to require any additional variable while keeping the code readable.
Algorithm library : https://en.cppreference.com/w/cpp/algorithm
精彩评论