繁体   English   中英

从两个向量创建一个地图

[英]creating a map from two vectors

如果我有两个stl向量vect1,vect2和我想从它们生成一个映射,那么vect1中的第一个元素将对应于vect2中的第一个元素,依此类推。 我怎么能以最简单的方式做到这一点?

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];

这是一个使用标准库函数(和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";
});

注意:这假定vec1.size()不大于vec2.size()。

我们将使用带有 2个输入序列的std :: transform版本。 (众所周知,它看起来像是一个单一序列)。

您可以传入std::make_pair<v1::value_type, v2::value_type>作为您的变换器(op),因此在您的情况下

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&> );

我已经测试了代码,它与GNU 4.3.2编译得很好

(我现在也用C ++ 11进行了测试。当我改变make_pair以获取int const而不是int时,它可以工作。

如果两个输入序列的长度不同,如果第一个较短,则第二个序列中的后一个元素将被忽略,这将是正常的。 如果第一个更长,则会产生未定义的行为。

这是一个使用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;
}

好吧,这是一个使用std::transform简单版本,我不知道已经存在的东西可以将boost::tuple转换为std::pair因此我的简单函数...

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

假设,你将忽略额外的(vect1的大小!= vect2的大小),这可能是一个解决方案:

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

编辑:谢谢Nim指出* it1的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM