2010-04-02 38 views
7

給定multimap<A,B> M用特定鍵創建M中所有值的vector<B>的方法是什麼?使用給定鍵填充具有所有多圖值的矢量

例如給出一個multimap如何獲得映射到值123的所有字符串的向量?

答案答案很簡單,從下限→上限循環,但有沒有一個整潔的無循環方法?

+0

你怎麼會去每一個元素沒有循環? – GManNickG 2010-04-02 18:00:29

+0

因此,這個問題,尋找STL的詭計/魔術(爲我們做循環) – 2010-04-02 18:43:32

回答

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, ",")); 

} 
+0

那麼,select2nd的不在VC++ 2008呢? – 2010-04-02 18:45:23

+0

它存在於VC++ 2008附帶的Dinkumware頭文件中,但是它和其他幾個文件位於#ifdef _HAS_TRADITIONAL_STL內#endif – 2010-04-02 19:07:28

1

您可以通過給它兩個迭代器,像這樣的初始化向量:

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。

對於只提取值,我想不出任何方式,但循環播放結果,因爲我不知道一個標準的方法來獲得超出範圍的值。

+2

一個問題是,這將創建一個'vector >'而不是'vector ' – 2010-04-02 17:49:04

+0

Gack。你說得對,看起來我正確回答了錯誤的問題。 – 2010-04-02 17:51:37

2

無論如何你需要一個循環。所有「無循環」方法只是將循環抽象出來。

#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; 
} 
+0

當然,他們把它抽象出來,這就是問題的關鍵!我認爲你的asnwer是我正在尋找的那種東西,但是我沒有意識到select2nd是非標準的。它在MSVC++嗎? – 2010-04-02 18:35:58

+0

@John:在MSDN中找不到它。但是很容易寫出一個函子'template U select2nd_f(const std :: pair &p){return p.second; }' – kennytm 2010-04-02 18:47:17

1
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; 
} 
+0

爲什麼要返回一個引用?爲什麼限制用戶一次只能使用1個鍵? – kennytm 2010-04-02 20:58:44

+0

1.爲什麼不呢? 2.因爲這是OP要求的。 – 2010-04-02 21:30:35

2

走吧拉姆達

給出: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;});   

系統環境:

  1. 編譯器:GCC(Ubuntu的5.3.1-14ubuntu2.1)5.3.1 20160413(帶有-std = C++ 11)
  2. OS: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; 
}