Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Сравните два последовательных элемента в std::list

Автор вопроса: CommunityОтветов: 4

Я хотел бы сравнить два последовательных элемента в std::list при переборе списка. Как правильно получить доступ к элементу i+1, пока мой итератор находится в элементе i? Спасибо, Кобе.

  • Если возможно, вы можете изменить заголовок вопроса на Как сравнить ДВА последовательных элемента в std::list?. Я бы сделал это сам, но у меня нет репутации ;-) Tom Williams 04.11.2008

c++listiteratorcompare

Ответы

Ответ 1 · рейтинг 12 · Nicola Bonelli

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 );

Ответ 2 · рейтинг 10 · Chris Jester-Young

У Boost есть утилита под названием next (и ее обратная, prior) именно для этого. цель.

*itr == *next(itr)

Редактировать: Но если мы вернемся назад, чтобы взглянуть на лес, настоящий вопрос заключается в том, зачем писать свой собственный adjacent_find функция? (Я рекомендую принять ответ Николы Бонелли.) Это часть STL и не требует использования Boost, если ваш код не использует Boost (спасибо комментаторам за указание на это).

Ответ 3 · рейтинг 8 · Motti

Проще всего было бы удерживать два итератора (поскольку вам все равно придется остановиться на предпоследнем).

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 и почему я думаю, что это не подходит для этого варианта использования.

Ответ 4 · рейтинг 1 · Steve Jessop

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

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.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы