Цитирование на итераторах С++, начиная со второго (или n-го) элемента
Я ищу читаемый, элегантный способ сделать следующее на С++, здесь показано на 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.
}
Он не слишком длинный, но он вряд ли раскрыт - на первый взгляд это на самом деле выглядит как ошибка!
Другое решение - иметь вспомогательную функцию "n-го элемента", я думаю. Любые более прохладные идеи?
Ответы
Ответ 1
Вы можете использовать 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
, иначе код будет катастрофическим.
Ответ 2
#include <iterator>
iterator iter = data.begin();
for (advance(iter, 1); iter != data.end(); ++iter)
{
// do work
}
Это полагается нa >= 1 элемент в data
, чтобы избежать исключения.
Ответ 3
Вы можете попробовать:
for (mIter = data.begin() ; ++mIter != data.end() ; )
но вам нужно убедиться, что если data.begin () == data.end ()
выполнение ++mIter
не вызывает проблемы.
Поскольку это нестандартный цикл цикла, использование цикла while может быть более уместным, так как существует меньше предвзятых представлений о том, как они работают, то есть люди, смотрящие на ваш код, с большей вероятностью читают инструкцию while, чем оператор for так как обычно существует модель того, как цикл for должен работать в их голове.
mIter = data.begin ();
while (++mIter != data.end ())
{
}
Ответ 4
Вы можете использовать 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;
}
Ответ 5
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);
}