Данный a multimap<A,B>
M, что аккуратный путь состоит в том, чтобы создать a vector<B>
из всех значений в M с определенным ключом.
например, учитывая мультикарту, как я могу получить вектор всех строк, отображенных на значении 123?
Ответ легок, цикличное выполнение от ниже-> верхняя граница, но является там аккуратным методом без циклов?
Вот способ сделать это в стиле STL:
// The following define is needed for select2nd with DinkumWare STL under VC++
#define _HAS_TRADITIONAL_STL 1
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <functional>
#include <map>
#include <iterator>
#include <iostream>
using namespace std;
void main()
{
typedef multimap<string, int> MapType;
MapType m;
vector<int> v;
// Test data
for(int i = 0; i < 10; ++i)
{
m.insert(make_pair("123", i * 2));
m.insert(make_pair("12", i));
}
MapType::iterator i = m.lower_bound("123");
MapType::iterator j = m.upper_bound("123");
transform(i, j, back_inserter(v), select2nd<MapType::value_type>());
copy(v.begin(), v.end(), ostream_iterator<int>(cout, ","));
}
Вы можете инициализировать вектор, задав ему два итератора, например:
std::multimap<std::string, std::string> bar;
...
std::vector<pair<string,string> > foo(bar.lower_bound("123"), bar.upper_bound("123"));
, но это даст вам вектор пар (т. Е. С обоими ключ и значение).
Другой вариант - использовать std :: copy
с чем-то вроде back_inserter, что является еще одним способом скрыть цикл, но с теми же недостатками, что и выше.
std::copy(bar.lower_bound("123"), bar.upper_bound("123"), std::back_inserter(foo));
Это добавит элементы (если есть) к вектору foo.
Для извлечения только значений я не могу придумать никакого способа, кроме как перебирать результаты, поскольку я не знаю стандартного способа получить только значение из диапазона.
Вам в любом случае нужен цикл. Все "свободные от цикла" методы просто абстрагируют цикл.
#include <map>
#include <vector>
#include <algorithm>
#include <ext/functional>
using namespace std;
int main () {
multimap<int, double> mm;
mm.insert(make_pair(1, 2.2));
mm.insert(make_pair(4, 2.6));
mm.insert(make_pair(1, 9.1));
mm.insert(make_pair(1, 3.1));
vector<double> v;
transform(mm.lower_bound(1), mm.upper_bound(1),
back_inserter(v), __gnu_cxx::select2nd<pair<int, double> >());
// note: select2nd is an SGI extension.
for (vector<double>::const_iterator cit = v.begin(); cit != v.end(); ++ cit)
printf("%g, ", *cit); // verify that you've got 2.2, 9.1, 3.1
return 0;
}
template <class Key, class Val>
vector<Val>& getValues(multimap<Key, Val>& multi, Key& key)
{
typedef multimap<Key, Val>::iterator imm;
static vector<Val> vect;
static struct
{
void operator()(const pair<Key, Val>& p) const
{
vect.push_back(p.second);
}
} Push;
vect.clear();
pair<imm, imm> range = multi.equal_range(key);
for_each(range.first, range.second, Push);
return vect;
}
Это немного надумано из-за вашего требования «без цикла».
Я предпочитаю:
template <class Key, class Val>
vector<Val> getValues(multimap<Key, Val>& map, Key& key)
{
vector<Val> result;
typedef multimap<Key, Val>::iterator imm;
pair<imm, imm> range = map.equal_range(key);
for (imm i = range.first; i != range.second; ++i)
result.push_back(i->second);
return result;
}