Заполните вектор всеми значениями multimap заданным ключом
дали multimap<A,B>
M что такое аккуратный способ создать vector<B>
всех значений в M с определенным ключом.
e.g учитывая multimap, как я могу получить вектор всех строк, сопоставленных со значением 123?
An ответ прост, петля из нижней - > верхней границы, но есть ли аккуратный метод без петли?
5 ответов
вот как это сделать в стиле 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, ","));
}
пойдем лямбда
дано: multimap<A,B> M
требуется: vector<B>
(всех значений в M с определенным ключом "a".)
способ:
std::pair<M::iterator, M::iterator> aRange = M.equal_range('a')
std::vector<B> aVector;
std::transform(aRange.first, aRange.second,std::back_inserter(aVector), [](std::pair<A,B> element){return element.second;});
системные требования:
- компилятор: gcc (Ubuntu 5.3.1-14ubuntu2.1) 5.3.1 20160413 (с-std=c++11)
- ОС: ubuntu 16.04
пример кода:
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <functional>
#include <iostream>
int main()
{
typedef std::multimap<std::string, int> MapType;
MapType m;
std::vector<int> v;
/// Test data
for(int i = 0; i < 10; ++i)
{
m.insert(std::make_pair("123", i * 2));
m.insert(std::make_pair("12", i));
}
std::pair<MapType::iterator,MapType::iterator> aRange = m.equal_range("123");
std::transform(aRange.first, aRange.second, std::back_inserter(v), [](std::pair<std::string,int> element){return element.second;});
for(auto & elem: v)
{
std::cout << elem << std::endl;
}
return 0;
}
вам все равно нужен цикл. Все" свободные от цикла " методы просто абстрагируют цикл.
#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;
}
вы можете инициализировать вектор, дав ему два итератора, например:
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.
для извлечения только значений я не могу подумайте о любом способе, кроме цикла результатов, поскольку я не знаю стандартного способа получить только значение из диапазона.
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;
}