Create a map of two vectors

If I have two stl vectors vect1, vect2, and I want to create a map from them, so the first element from vect1 will correspond to the first element in vect2, etc. How can I do this in the easiest way?

+4
source share
5 answers
std::vector<int> a, b; // fill vectors here... std::map<int, int> m; assert(a.size() == b.size()); for (size_t i = 0; i < a.size(); ++i) m[a[i]] = b[i]; 
+7
source

Here is a solution that uses standard library functions (and C ++ 0x lambdas).

 const int data1[] = { 0, 2, 4, 6, 8 }; const int data2[] = { 1, 3, 5, 7, 9 }; std::vector<int> vec1(data1, data1 + 5); std::vector<int> vec2(data2, data2 + 5); std::map<int,int> map; // create map std::transform(vec1.begin(), vec1.end(), vec2.begin(), std::inserter(map, map.end()), [](int a, int b) { return std::make_pair(a, b); }); // display map std::for_each(map.begin(), map.end(), [](const std::pair<int,int>& p) { std::cout << p.first << "," << p.second << "\n"; }); 

Note. It is assumed that vec1.size () is no larger than vec2.size ().

+6
source

We will use the version of std :: transform , which takes 2 input sequences. (It is not so well known that it appears as one that takes one sequence).

You can pass std::make_pair<v1::value_type, v2::value_type> as your transformer (op), so in your case

 std::vector<int> vec1, vec2; std::map< int, int > mergedMap; std::transform( vec1.begin(), vec1.end(), vec2.begin(), std::inserter(mergedMap, mergedMap.end() ), std::make_pair<int const&,int const&> ); 

I tested the code and compiles using GNU 4.3.2

(I also tested now with C ++ 11. It works when I changed make_pair to use int const & instead of int).

If the two input sequences have different lengths, it will be good if the first is shorter, and subsequent elements in the second sequence will be ignored. If the first is longer, it will create undefined behavior.

+3
source

Here is a small change that boost zip_iterator

 #include <iostream> #include <algorithm> #include <string> #include <map> #include <vector> #include <boost/iterator/zip_iterator.hpp> #include <boost/tuple/tuple.hpp> // this is our map type typedef std::map<int, std::string> map_t; // this functor will be called for each "pair" struct map_adder : public std::unary_function<const boost::tuple<const int&, const std::string&>&, void> { map_adder(map_t& my_map) : _my_map(my_map){} void operator()(const boost::tuple<const int&, const std::string&>& t) const { _my_map.insert(std::make_pair(t.get<0>(), t.get<1>())); } private: mutable map_t& _my_map; }; int main(void) { // test setup std::vector<int> keys; std::vector<std::string> values; keys.push_back(1); keys.push_back(2); keys.push_back(3); keys.push_back(4); values.push_back("1"); values.push_back("2"); values.push_back("3"); values.push_back("4"); std::vector<int>::const_iterator beg1 = keys.begin(); std::vector<int>::const_iterator end1 = keys.end(); std::vector<std::string>::const_iterator beg2 = values.begin(); std::vector<std::string>::const_iterator end2 = values.end(); // destination map_t my_map; // functor to actually add map_adder adder(my_map); // simply iterate over... std::for_each( boost::make_zip_iterator( boost::make_tuple(beg1, beg2) ), boost::make_zip_iterator( boost::make_tuple(end1, end2) ), adder ); std::cout << "size of map: " << my_map.size() << std::endl; return 0; } 

Okay, here is a simpler version using std::transform , I don't know what already exists that can convert boost::tuple to std::pair , hence my simple function ...

 #include <iostream> #include <algorithm> #include <string> #include <iterator> #include <map> #include <vector> #include <boost/iterator/zip_iterator.hpp> #include <boost/tuple/tuple.hpp> // this is our map type typedef std::map<int, std::string> map_t; map_t::value_type adapt_tuple(const boost::tuple<const map_t::key_type&, const map_t::mapped_type&>& t) { return map_t::value_type(t.get<0>(), t.get<1>()); } int main(void) { std::vector<int> keys; std::vector<std::string> values; keys.push_back(1); keys.push_back(2); keys.push_back(3); keys.push_back(4); values.push_back("1"); values.push_back("2"); values.push_back("3"); values.push_back("4"); std::vector<int>::const_iterator beg1 = keys.begin(); std::vector<int>::const_iterator end1 = keys.end(); std::vector<std::string>::const_iterator beg2 = values.begin(); std::vector<std::string>::const_iterator end2 = values.end(); map_t my_map; // simply iterate over... std::transform( boost::make_zip_iterator( boost::make_tuple(beg1, beg2) ), boost::make_zip_iterator( boost::make_tuple(end1, end2) ), std::inserter(my_map, my_map.end()), adapt_tuple ); std::cout << "size of map: " << my_map.size() << std::endl; return 0; } 
+1
source

Assuming you ignore the extra (size vect1! = Size vect2), this might be a solution:

 map<T1, T2> target; //vector<T1> vect1, vector<T2> vect2; vector<T1>::iterator it1 = vect1.begin(); vector<T2>::iterator it2 = vect2.begin(); while(it1 != vect1.end() && it2 != vect2.end()) { target.insert(std::make_pair(*it1, *it2)); it1++;it2++; } 

EDIT: Thanks to Nim for pointing out * it1 thing.

0
source

Source: https://habr.com/ru/post/1339041/


All Articles