Я хотел бы сравнить два последовательных элемента в std::list при переборе списка. Как правильно получить доступ к элементу i+1, пока мой итератор находится в элементе i? Спасибо, Кобе.
Сравните два последовательных элемента в std::list
Ответы (4)
12
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 );
10
У Boost есть утилита под названием next (и ее обратная, prior) именно для этого. цель.
*itr == *next(itr)
Редактировать: Но если мы вернемся назад, чтобы взглянуть на лес, настоящий вопрос заключается в том, зачем писать свой собственный adjacent_find функция? (Я рекомендую принять ответ Николы Бонелли.) Это часть STL и не требует использования Boost, если ваш код не использует Boost (спасибо комментаторам за указание на это).
std::next и std::prev, что в данном случае делает бустинг ненужным.
- person ; 27.04.2013
8
Проще всего было бы удерживать два итератора (поскольку вам все равно придется остановиться на предпоследнем).
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и почему я думаю, что это не подходит для этого варианта использования.
1
Список является обратимым контейнером, поэтому его итераторы являются двунаправленными итераторами, которые являются моделью прямого итератора, что, я почти уверен, означает, что вы можете сделать это (или что-то подобное, если у вас аллергия на вырваться из середины петля и др.):
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.