2011-06-01 88 views
4

我想知道是否有任何技巧使用地圖複製功能將地圖內容複製到數組中。由於STL地圖由鍵值和映射值組合,因此地圖的元素形成鍵值對。這阻止了我們使用標準算法,如std :: copy。例如下面的代碼提供了錯誤:是否可以使用地圖的STL複製功能

#include <iostream> 
#include <algorithm> 
#include <vector> 
#include <map> 

int 
main() 
{ 
    std::map <int, double> test(4); 
    test[0] = 11; 
    test[2] = 1.23; 
    test[3] = 23.29; 
    test[1] = 12.12; 
    double *test_arr = (double *) malloc(4 * sizeof(double)); 
    std::copy(test.begin(), test.end(), test_arr); 
    std::cout << test_arr[3] << std::endl; 
    return 0; 
} 

錯誤:

stl_copy_tests.cpp: In function ‘int main()’: 
stl_copy_tests.cpp:9:32: error: no matching function for call to ‘std::map<int, double>::map(int)’ 
/usr/include/c++/4.5/bits/stl_map.h:170:7: note: candidates are: std::map<_Key, _Tp, _Compare, _Alloc>::map(const std::map<_Key, _Tp, _Compare, _Alloc>&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, std::map<_Key, _Tp, _Compare, _Alloc> = std::map<int, double>] 
/usr/include/c++/4.5/bits/stl_map.h:159:7: note:     std::map<_Key, _Tp, _Compare, _Alloc>::map(const _Compare&, const allocator_type&) [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >, allocator_type = std::allocator<std::pair<const int, double> >] 
/usr/include/c++/4.5/bits/stl_map.h:150:7: note:     std::map<_Key, _Tp, _Compare, _Alloc>::map() [with _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, double> >] 
In file included from /usr/include/c++/4.5/bits/char_traits.h:41:0, 
       from /usr/include/c++/4.5/ios:41, 
       from /usr/include/c++/4.5/ostream:40, 
       from /usr/include/c++/4.5/iostream:40, 
       from stl_copy_tests.cpp:1: 
/usr/include/c++/4.5/bits/stl_algobase.h: In static member function ‘static _OI std::__copy_move<<anonymous>, <anonymous>, <template-parameter-1-3> >::__copy_m(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*, bool <anonymous> = false, bool <anonymous> = false, <template-parameter-1-3> = std::bidirectional_iterator_tag]’: 
/usr/include/c++/4.5/bits/stl_algobase.h:404:70: instantiated from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’ 
/usr/include/c++/4.5/bits/stl_algobase.h:442:39: instantiated from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false, _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’ 
/usr/include/c++/4.5/bits/stl_algobase.h:474:18: instantiated from ‘_OI std::copy(_II, _II, _OI) [with _II = std::_Rb_tree_iterator<std::pair<const int, double> >, _OI = double*]’ 
stl_copy_tests.cpp:15:47: instantiated from here 
/usr/include/c++/4.5/bits/stl_algobase.h:319:6: error: cannot convert ‘std::pair<const int, double>’ to ‘double’ in assignment 

有沒有簡單的把戲/黑客來克服這個問題。

聲明:對在for循環中迭代映射的解決方案不感興趣,並向元素添加元素。除非,是的,你自己把它打開

+0

在您免責聲明:你到底是什麼做你認爲'std :: copy'呢? – Xeo 2011-06-01 11:10:42

+1

@Xeo:他意味着他不想在他的代碼中寫出循環。 – 2011-06-01 11:11:49

+0

重度相關:http://stackoverflow.com/questions/771453/copy-map-values-to-vector-in-stl – 2011-06-01 11:12:41

回答

5

你可以使用std::transform代替:

template <typename T, typename U> 
const U &extract_second(const std::pair<T,U> &p) 
{ 
    return p.second; 
} 

std::transform(test.begin(), test.end(), test_arr, extract_second<int,double>); 

而作爲@Andre在下面評論指出,如果你想有一個稍微詳細的開銷,從而可以避免通過仿函數來明確說明模板參數:

struct extract_second 
{ 
    template <typename T, typename U> 
    const U operator() (const std::pair<T,U> &p) const 
    { 
     return p.second; 
    } 
}; 

std::transform(test.begin(), test.end(), test_arr, extract_second()); 

我確定有一個使用Boost粘合劑的較不詳細的解決方案,但我記不起頭頂的語法。

+2

我喜歡寫'extract_second'爲:'struct extract_second {template const U&operator()(const std :: pair &p){return p.second;} const};'你可以省略調用中的模板參數:'std :: transform(test.begin(),test.end(),test_arr,extract_second());' – 2011-06-01 11:28:42

+0

@Andre:謝謝!我已將您的版本集成到我的答案中。 – 2011-06-01 11:38:50

+0

感謝奧利,我忘了使用std :: transform,同時詹姆斯指出了從地圖中提取值的提升方式。 – systemsfault 2011-06-01 11:50:00

2

你的目標將是一個 陣列 std::vector[請!] std::pair<int,double>對象

(你可以創建自己的InputIterator作爲代理,或與std::transformstd::back_inserter玩,但只是不懂事,你會讓你的代碼遠比僅僅通過地圖循環更詳細。)

+1

或者,如果你想要一個雙打數組並且不想寫一個循環,你可以而是寫一個輸出迭代器,用'operator =(const pair &p){*(this-> underlying_ptr)= p.second; }'。 Boost迭代器助手可能會有這樣做,我沒有看過。 – 2011-06-01 11:12:48

+0

@Steve:是的,你可以像'InputIterator'一樣容易地將邏輯應用於'OutputIterator'。可能更容易,現在你提到它。 – 2011-06-01 11:13:36

4

Ewww,malloc?無論如何,如果你想複製地圖,你也必須記住鑰匙。

int main() 
{ 
    std::map <int, double> test(4); 
    test[0] = 11; 
    test[2] = 1.23; 
    test[3] = 23.29; 
    test[1] = 12.12; 
    std::vector<std::pair<int, double>> test_arr(test.size()); 
    std::copy(test.begin(), test.end(), test_arr.begin()); 
    std::cout << test_arr[3] << std::endl; 
    return 0; 
} 
2

如果你考慮std::map STL容器,那麼它的 std::pair<key_type, mapped_type>的容器。 (這是它的value_type被定義爲 ,它被設計成它可以用作容器的一個 )。如果你只需要它的一部分,正確的功能是 std::transform,帶有一個轉換函數映射 value_typekey_typemapped_type。 (如果您 多大用處的std::pair —或std::map,其value_typestd::pair,你應該有這個功能對象 您的工具包:

struct ExtractFirst 
{ 
    template<typename Pair> 
    typename boost::remove_const<typename Pair::first_type>::type 
         operator()(Pair const& from) const 
    { 
     return from.first; 
    } 
}; 

,並ExtractSecond同樣的事情。

2

最簡單的方法是結合使用std::transformboost::bind

typedef std::map<int, double> map_t; 
map_t mm; 

// add elements to mm 
// ... 

// copy 
typedef std::vector<double> vec_t; 
vec_t vv; 
vv.reserve(mm.size()); 
std::transform(mm.begin(), mm.end(), std::back_inserter(vv), 
    boost::bind(&map_t::value_type::second, _1)); 

如果你可以用的C++ 0x(不boost):

std::transform(mm.begin(), mm.end(), back_inserter(vv), 
    [](map_t::value_type val) -> double { return val.second; }); 
// or 
std::for_each(mm.begin(), mm.end(), 
    [&vv](map_t::value_type val) { vv.push_back(val.second); }); 
相關問題