std::transform
будет самым идиоматическим способом. Вам нужен функционал
объект:
template<typename PairType>
struct Second
{
typename PairType::second_type operator()( PairType const& obj ) const
{
return obj.second;
}
}
(Если вы много работаете с std::map
или другими вещами, которые используют
std::pair
, вы будете иметь это в своем наборе инструментов.)
После этого это немного неловко, потому что вам нужен только последний n. поскольку
итераторы в карту не являются итераторами с произвольным доступом, и вы не можете добавить
или вычесть произвольные значения, самое простое решение состоит в том, чтобы скопировать их все,
затем удалите ненужные:
std::vector<MyType>
extractLastN( std::map<double, MyType> const& source, size_t n )
{
std::vector<MyType> results;
std::transform( source.begin(), source.end(),
std::back_inserter( results ),
Second<std::map<double, MyType>::value_type>() );
if ( results.size() > n ) {
results.erase( results.begin(), results.end() - n );
}
return results;
}
Это не самый эффективный, но зависит от n
и где это
используется, это может быть достаточно. Если вы хотите избежать дополнительного копирования,
и т. д. (вероятно, стоит только если n
обычно намного меньше, чем
размером с карту), вам придется заняться чем-то более причудливым:
std::vector<MyType>
extractLastN( std::map<double, MyType> const& source, ptrdiff_t n )
{
std::map<double, MyType>::const_iterator start
= source.size() <= n
? source.begin()
: std::prev( source.end(), n );
std::vector<MyType> results;
std::transform( start, source.end(),
std::back_inserter( results ),
Second<std::map<double, MyType>::value_type>() );
return results;
}
(Если у вас нет доступа к C ++ 11, std::prev
это просто:
template<typename IteratorType>
IteratorType
prev( IteratorType start, ptrdiff_t n )
{
std::advance( start, -n );
return start;
}
Опять же, если вы много делаете со стандартной библиотекой, вы, вероятно,
уже есть в вашем наборе.)