Как я могу обнаружить последнюю итерацию в цикле над std :: map? - PullRequest
27 голосов
/ 30 сентября 2008

Я пытаюсь найти лучший способ определить, нахожусь ли я на последней итерации цикла над картой, чтобы сделать что-то вроде следующего:

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    bool last_iteration;
    // do something for all iterations
    if (!last_iteration) {
        // do something for all but the last iteration
    }
}

Кажется, есть несколько способов сделать это: итераторы с произвольным доступом, функция distance и т. Д. Что такое канонический метод?

Редактировать: нет итераторов произвольного доступа для карт!

Ответы [ 14 ]

25 голосов
/ 30 сентября 2008

Canonical? Я не могу утверждать это, но я бы предложил

final_iter = someMap.end();
--final_iter;
if (iter != final_iter) ...

Отредактировано для исправления в соответствии с предложением KTC . (Спасибо! Иногда вы идете слишком быстро и путаетесь в самых простых вещах ...)

16 голосов
/ 11 декабря 2015

Начиная с C ++ 11, вы также можете использовать std :: next ()

   for (auto iter = someMap.begin(); iter != someMap.end(); ++iter) { 
        // do something for all iterations
        if (std::next(iter) != someMap.end()) {
            // do something for all but the last iteration
        }
    }

Хотя вопрос был задан некоторое время назад, я подумал, что стоит поделиться.

14 голосов
/ 30 сентября 2008

Это кажется самым простым:

bool last_iteration = iter == (--someMap.end());
10 голосов
/ 30 сентября 2008

Если вы просто хотите использовать ForwardIterator, это должно работать:

for ( i = c.begin(); i != c.end(); ) {
        iterator cur = i++;
        // do something, using cur
        if ( i != c.end() ) {
                // do something using cur for all but the last iteration
        }
}
6 голосов
/ 30 января 2009

Удивило, что никто еще не упомянул об этом, но, конечно, в boost есть что-то;)

Boost.Next (и эквивалентный Boost.Prior)

Ваш пример будет выглядеть так:

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    // do something for all iterations
    if (boost::next(iter) != someMap.end()) {
        // do something for all but the last iteration
    }
}
6 голосов
/ 30 сентября 2008

Модифицировано Mark Ransom's, чтобы оно действительно работало как задумано.

finalIter = someMap.end();
--finalIter;
if (iter != final_iter)
3 голосов
/ 08 декабря 2011

Следующий код будет оптимизирован компилятором так, чтобы быть лучшим решением для этой задачи как по производительности, так и по правилам ООП:

if (&*it == &*someMap.rbegin()) {
    //the last iteration
}

Это лучший код по правилам ООП, потому что в std :: map есть специальная функция-член rbegin для кода, подобного:

final_iter = someMap.end();
--final_iter;
1 голос
/ 06 апреля 2013

Зачем работать, чтобы найти EOF, чтобы вы ничего не давали ему.

Просто исключите его;

for (iter = someMap.begin(); someMap.end() - 1; ++iter) {
    //apply to all from begin to second last element
}

ПОЦЕЛУЙ (ПРОДОЛЖАЙТЕ ПРОСТО)

1 голос
/ 30 сентября 2008
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <algorithm>

using namespace boost::lambda;

// call the function foo on each element but the last...
if( !someMap.empty() )
{
  std::for_each( someMap.begin(), --someMap.end(), bind( &Foo, _1 ) );
}

Использование std :: for_each обеспечит плотный и точный цикл ... Обратите внимание на введение функции foo (), которая принимает один аргумент (тип должен соответствовать тому, что содержится в someMap). В этом подходе добавлена ​​1 строка. Конечно, если Foo действительно маленький, вы можете использовать лямбда-функцию и избавиться от вызова & Foo.

0 голосов
/ 02 ноября 2015

Как насчет этого, никто не упоминает, но ...

for (iter = someMap.begin(); iter != someMap.end(); ++iter) {
    // do something for all iterations
    if (iter != --someMap.end()) {
        // do something for all but the last iteration
    }
}

это кажется простым, мм ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...