Заполните вектор со всеми значениями мультикарты с данным ключом

Данный a multimap<A,B> M, что аккуратный путь состоит в том, чтобы создать a vector<B> из всех значений в M с определенным ключом.

например, учитывая мультикарту, как я могу получить вектор всех строк, отображенных на значении 123?

Ответ легок, цикличное выполнение от ниже-> верхняя граница, но является там аккуратным методом без циклов?

10
задан Mr. Boy 2 April 2010 в 17:43
поделиться

4 ответа

Вот способ сделать это в стиле 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, ","));

}
6
ответ дан 3 December 2019 в 23:12
поделиться

Вы можете инициализировать вектор, задав ему два итератора, например:

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.

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

1
ответ дан 3 December 2019 в 23:12
поделиться

Вам в любом случае нужен цикл. Все "свободные от цикла" методы просто абстрагируют цикл.

#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;
}
2
ответ дан 3 December 2019 в 23:12
поделиться
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;
}
2
ответ дан 3 December 2019 в 23:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: