将地图值复制到STL中的vector

目前正在通过有效的STL工作。 第5项build议通常最好将范围成员函数用于其单个元素对应项。 我现在希望将所有的值都映射到一个向量中(也就是我不需要这个键)。

最干净的方法是什么?

在这里你不能轻易使用范围,因为你从映射得到的迭代器引用了一个std :: pair,其中你要用来插入到一个向量中的迭代器引用了存储在向量中的types的对象, (如果你丢弃钥匙)不是一对。

我真的不认为它比显而易见的更清洁:

#include <map> #include <vector> #include <string> using namespace std; int main() { typedef map <string, int> MapType; MapType m; vector <int> v; // populate map somehow for( MapType::iterator it = m.begin(); it != m.end(); ++it ) { v.push_back( it->second ); } } 

如果我不止一次地使用它,我可能会重写为模板函数。 就像是:

 template <typename M, typename V> void MapToVec( const M & m, V & v ) { for( typename M::const_iterator it = m.begin(); it != m.end(); ++it ) { v.push_back( it->second ); } } 

为此,你可以使用std::transform 。 我可能会更喜欢Neils版本,这取决于更可读的内容。


xtofl示例(请参阅注释):

 #include <map> #include <vector> #include <algorithm> #include <iostream> template< typename tPair > struct second_t { typename tPair::second_type operator()( const tPair& p ) const { return p.second; } }; template< typename tMap > second_t< typename tMap::value_type > second( const tMap& m ) { return second_t< typename tMap::value_type >(); } int main() { std::map<int,bool> m; m[0]=true; m[1]=false; //... std::vector<bool> v; std::transform( m.begin(), m.end(), std::back_inserter( v ), second(m) ); std::transform( m.begin(), m.end(), std::ostream_iterator<bool>( std::cout, ";" ), second(m) ); } 

非常通用,如果您觉得它有用,请记得给他信用。

如果你正在使用boost库 ,你可以使用boost :: bind来访问这个对的第二个值,如下所示:

 #include <string> #include <map> #include <vector> #include <algorithm> #include <boost/bind.hpp> int main() { typedef std::map<std::string, int> MapT; typedef std::vector<int> VecT; MapT map; VecT vec; map["one"] = 1; map["two"] = 2; map["three"] = 3; map["four"] = 4; map["five"] = 5; std::transform( map.begin(), map.end(), std::back_inserter(vec), boost::bind(&MapT::value_type::second,_1) ); } 

这个解决scheme是基于Michael Goldshteyn在boost邮件列表中的一篇文章。

使用lambdas可以执行以下操作:

 { std::map<std::string,int> m; std::vector<int> v; v.reserve(m.size()); std::for_each(m.begin(),m.end(), [&v](const std::map<std::string,int>::value_type& p) { v.push_back(p.second); }); } 

老问题,新答案。 用C ++ 11,我们有了新的循环:

 for (const auto &s : schemas) names.push_back(s.first); 

模式是一个std::map而names是一个std::vector

这使用来自映射(模式)的键填充数组(名称); 将s.first更改为s.second以获取值的数组。

这是我会做的。
另外我会使用一个模板函数来使select2nd的构造更容易。

 #include <map> #include <vector> #include <algorithm> #include <memory> #include <string> /* * A class to extract the second part of a pair */ template<typename T> struct select2nd { typename T::second_type operator()(T const& value) const {return value.second;} }; /* * A utility template function to make the use of select2nd easy. * Pass a map and it automatically creates a select2nd that utilizes the * value type. This works nicely as the template functions can deduce the * template parameters based on the function parameters. */ template<typename T> select2nd<typename T::value_type> make_select2nd(T const& m) { return select2nd<typename T::value_type>(); } int main() { std::map<int,std::string> m; std::vector<std::string> v; /* * Please note: You must use std::back_inserter() * As transform assumes the second range is as large as the first. * Alternatively you could pre-populate the vector. * * Use make_select2nd() to make the function look nice. * Alternatively you could use: * select2nd<std::map<int,std::string>::value_type>() */ std::transform(m.begin(),m.end(), std::back_inserter(v), make_select2nd(m) ); } 
 #include <algorithm> // std::transform #include <iterator> // std::back_inserter std::transform( your_map.begin(), your_map.end(), std::back_inserter(your_values_vector), [](auto &kv){ return kv.second;} ); 

对不起,我没有添加任何解释 – 我认为代码是如此简单,不需要任何解释。 所以:

 transform( beginInputRange, endInputRange, outputIterator, unaryOperation) 

这个函数在inputIterator范围( beginInputRangeendInputRange )的每个项目上调用unaryOperation 。 操作的值存储在outputIterator

如果我们想通过整个地图进行操作 – 我们使用map.begin()和map.end()作为我们的input范围。 我们希望将我们的地图值存储到vector中 – 所以我们必须在我们的vector上使用back_inserter: back_inserter(your_values_vector) 。 back_inserter是特殊的outputIterator,它在给定(作为参数)集合的末尾推送新的元素。 最后一个参数是unaryOperation – 它只接受一个参数 – inputIterator的值。 所以我们可以使用lambda: [](auto &kv) { [...] } ,其中&kv只是对映射项对的引用。 所以如果我们只想返回地图项的值,我们可以简单的返回kv.second:

 [](auto &kv) { return kv.second; } 

我认为这解释了任何怀疑。

我以为应该是

std :: transform(map.begin(),map.end(),std :: back_inserter(vec),boost :: bind(&MapT :: value_type :: first,_1));

一种方法是使用函子:

  template <class T1, class T2> class CopyMapToVec { public: CopyMapToVec(std::vector<T2>& aVec): mVec(aVec){} bool operator () (const std::pair<T1,T2>& mapVal) const { mVec.push_back(mapVal.second); return true; } private: std::vector<T2>& mVec; }; int main() { std::map<std::string, int> myMap; myMap["test1"] = 1; myMap["test2"] = 2; std::vector<int> myVector; //reserve the memory for vector myVector.reserve(myMap.size()); //create the functor CopyMapToVec<std::string, int> aConverter(myVector); //call the functor std::for_each(myMap.begin(), myMap.end(), aConverter); } 

为什么不:

 template<typename K, typename V> std::vector<V> MapValuesAsVector(const std::map<K, V>& map) { std::vector<V> vec; vec.reserve(map.size()); std::for_each(std::begin(map), std::end(map), [&vec] (const std::map<K, V>::value_type& entry) { vec.push_back(entry.second); }); return vec; } 

用法:

auto vec = MapValuesAsVector(anymap);