Цикл на итераторах C ++, начиная со второго (или n-го) элемента - PullRequest
12 голосов
/ 18 ноября 2010

Я ищу читаемый, элегантный способ сделать следующее на C ++, здесь показано на Python:

for datum in data[1:]:
    do work.

Итераторы в данных могут не поддерживать итераторы произвольного доступа, поэтому я могупросто используйте:

for (mIter = data.begin() + 1; mIter != data.end(); mIter++)

Лучшее, что я придумал, это следующее:

iterable::iterator mIter = data.begin();
for (mIter++;  mIter != allMjds.end(); mjdIter++) {
    do work.
}

Это не слишком долго, но вряд ли объясняет - на первый взгляд это на самом делевыглядит как ошибка!

Другое решение - иметь вспомогательную функцию "nth element", я полагаю.Есть идеи круче?

Ответы [ 5 ]

23 голосов
/ 18 ноября 2010

Вы можете использовать std::next(iter, n) для линейного аванса. Вы также можете использовать стандартный алгоритм std::advance, хотя его не так просто использовать (он берет итератор по неконстантной ссылке и не возвращает его).

Например,

for (mIter = std::next(data.begin()); mIter != data.end(); ++mIter)

или

mIter = data.begin();
std::advance(mIter, 1);
for (; mIter != data.end(); ++mIter)

Обратите внимание, что вы должны убедиться, что data.size() >= 1, в противном случае код не получится катастрофическим образом.

5 голосов
/ 18 ноября 2010
#include <iterator>

iterator iter = data.begin();
for (advance(iter, 1); iter != data.end(); ++iter)
{
  // do work
}

Это полагается на> = 1 элемент в data, чтобы избежать исключения.

2 голосов
/ 18 ноября 2010

Вы можете попробовать:

for (mIter = data.begin() ; ++mIter != data.end() ; )

, но вам нужно убедиться, что если data.begin () == data.end () выполнение ++mIter не вызовет проблемы.

Так как этонестандартный цикл for, использование цикла while может быть более уместным, так как существует меньше предвзятых представлений о том, как они работают, то есть люди, просматривающие ваш код, с большей вероятностью будут читать оператор while, чем оператор for, поскольку обычно существует модельо том, как цикл for должен работать в их голове.

mIter = data.begin ();

while (++mIter != data.end ())
{
}
1 голос
/ 18 ноября 2010
iterable::iterator mIter = data.begin();    
std::for_each(++mIter, data.end(), some_func);

, где some_func содержит код, который вы хотите выполнить ... вы можете даже тривиализировать его с помощью простой функции-оболочки

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);
}
1 голос
/ 18 ноября 2010

Для этого вы можете использовать boost :: next (но вы должны быть уверены, что в списке действительно есть элемент, прежде чем это сделать):

#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;
}
...