开发者

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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜