Я хотел бы сравнить два последовательных элемента в std::list при переборе списка. Как правильно получить доступ к элементу i+1, пока мой итератор находится в элементе i? Спасибо, Кобе.
Сравните два последовательных элемента в std::list
Ответы (4)
STL предоставляет алгоритм смежных_найти(), который можно использовать для поиска двух последовательных одинаковых элементов. Существует также версия с пользовательским предикатом.
Это прототипы:
template <class ForwardIterator>
ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last );
template <class ForwardIterator, class BinaryPredicate>
ForwardIterator adjacent_find ( ForwardIterator first, ForwardIterator last,
BinaryPredicate pred );
У Boost есть утилита под названием next (и ее обратная, prior) именно для этого. цель.
*itr == *next(itr)
Редактировать: Но если мы вернемся назад, чтобы взглянуть на лес, настоящий вопрос заключается в том, зачем писать свой собственный adjacent_find функция? (Я рекомендую принять ответ Николы Бонелли.) Это часть STL и не требует использования Boost, если ваш код не использует Boost (спасибо комментаторам за указание на это).
Проще всего было бы удерживать два итератора (поскольку вам все равно придется остановиться на предпоследнем).
std::list<int>::const_iterator second = list.begin(),
end = list.end();
if ( second != end ) // Treat empty list
for(std::list<int>::const_iterator first = second++; // Post-increment
second != end;
++first, ++second)
{
//...
}
Обратите внимание, что first инициализируется с помощью пост-инкремента second, поэтому, когда цикл начинается first, это list.begin(), а второй - list.begin()+1.
Крис Джестер-Янг указывает, что у boost есть функции next и prior, хотя я не знаком с этими функциями (за свои грехи), их реализация тривиальна (особенно с учетом того, что list имеет двунаправленные итераторы).
template <class Iterator>
Iterator next(Iterator i) // Call by value, original is not changed
{
return ++i;
}
// Implementing prior is left as an exercise to the reader ;o)
Я чувствую, что использование next не решает эту проблему, а также поддержку обоих итераторов, поскольку вы должны помнить, что next(i) не равно end() при каждом использовании.
Правки:
- Исправлена ошибка, если список был пуст благодаря комментарию Luc Touraille.
- Добавьте ссылку на
nextи почему я думаю, что это не подходит для этого варианта использования.
Список является обратимым контейнером, поэтому его итераторы являются двунаправленными итераторами, которые являются моделью прямого итератора, что, я почти уверен, означает, что вы можете сделать это (или что-то подобное, если у вас аллергия на вырваться из середины петля и др.):
if (!l.empty()) {
for (list<T>::const_iterator i = l.begin();;) {
const T &a = *i;
++i;
if (i == l.end()) break;
do_comparison(a, *i);
}
}
Вы не могли бы сделать это с помощью итератора ввода, потому что с ними значения «существуют» только до тех пор, пока у вас есть итератор. Но вы можете с Forward Iterator.