2011-01-28 2 views
1

Я хранением значений в станде :: КартаSTL контейнеры: итерация между двумя итераторами

Я нахожу два значение в карте, и я хочу итерацию между первым до последнего пункта - однако < = оператор не выполняется, так что я не могу сделать somethimng так:

void foobar(const DatedRecordset& recs, const double startstamp, const double endtstamp) 
    { 
     DatedRecordsetConstIter start_iter = recs.lower_bound(startstamp), end_iter = recs.lower_bound(endtstamp); 

     // Can't do this .... (<= not defined) 
     //for (DatedRecordsetConstIter cit = start_iter; cit <= end_iter; cit++) 

     /So have to resort to a hack like this: 
     for (DatedRecordsetConstIter cit = start_iter; cit != recs.end(); cit++) { 
      if ((*cit).first <= (*end_iter).first){ 
       //do something; 
      } 
      else 
       break; 
      } 
     } 
} 

есть ли более элегантный способ итерации между двумя известными итераторами?

+0

Вы можете использовать cit! = (End_iter + 1). –

+1

Это не будет работать для 'std :: map :: iterator'; он не имеет определенного оператора '+'. Использование чего-то типа boost :: next было бы, однако, предполагая, что 'end_iter' не' recs.end() '(в любом случае исходная спецификация будет недействительной в этом случае). –

+0

@Jeremiah Willcock: Вы правы, но оператор '++' может выполнить трюк 'new_end_iter = end_iter ++'. –

ответ

2

Используйте != вместо <=, и он будет делать то, что вы хотите.

void foobar(const DatedRecordset& recs, const double startstamp, const double endtstamp) 
{ 
    DatedRecordsetConstIter start_iter = recs.lower_bound(startstamp), 
          end_iter = recs.upper_bound(endtstamp); 

    for (DatedRecordsetConstIter cit = start_iter; cit != end_iter; ++cit) { 
    } 
} 
+0

Это проблема по отдельности относительно исходного кода: в этой версии 'cit' никогда не будет равным' end_iter' в цикле, тогда как исходный код имеет 'cit == end_iter' в последней итерации из-за использования '<='. –

+0

Я думаю, что использование 'upper_bound' для вычисления' end_iter' будет делать трюк. –

+0

@Jeremiah Это правда. Я изменил 'end_iter', чтобы использовать' upper_bound' для @Mark. –

1

Оператор <= отсутствует на std::map<>::iterator, но с использованием != на end_iter должен делать в основном то же самое. Если вы хотите включить конечный итератор в итерацию, используйте что-то вроде цикла do, чтобы выполнить тест != в конце.

1
struct ManipulateMatchingPairs { 
    template<class K, class V> 
    void operator()(const std::pair<K,V>& p) const { 
     // do with p.second as you please here. 
    } 
}; 

// ... 
std::for_each(start_iter, end_iter, ManipulateMatchingPairs()); 
+0

Отображаемый тип можно записать в код: 'DatedRecordset :: mapped_type'. Но я думаю, что этот подход пропускает любой элемент (ы) (если «multimap») равен «end_iter». –

+0

Я не буду следовать за тобой. «End_iter» всегда указывает на элемент «один-последний-последний». – wilhelmtell

0

Алгоритм STL for_each также не будет включать в себя конечный итератор в цикле. Вы всегда можете увеличивать end_iter и просто использовать for_each, чтобы он был включен.

void foobar(const DatedRecordset& recs, 
      const double startstamp, 
      const double endtstamp) 
{ 
    DatedRecordsetConstIter start_iter = recs.lower_bound(startstamp); 
    DatedRecordsetConstIter end_iter = recs.lower_bound(endtstamp); 
    if(end_iter != recs.end()) 
     ++end_iter; 

    for_each(start_iter, end_iter, []() 
     { 
      //do something inside the lambda. 
     }); 
} 

Что-то вроде этого может быть? Я не дал ему компиляционную проверку ...

0

Вы должны использовать оператор !=. Я считаю, что это потому, что std :: map не обязательно смежна в памяти (поэтому оператор <= не имеет большого смысла, тогда как std::vector будет), я мог бы ошибаться, хотя

0

Если вы хотите включить end iterator в цикле, вы можете увеличить ваш итератор конечного состояния ++end_iter. После этого цикл с cit != end_iter делает то же самое, что вы намерены делать с cit <= end_iter перед приращением.

Смежные вопросы