Скопировать карту значений вектора в STL
работая мой путь через эффективный STL на данный момент. Пункт 5 предполагает, что обычно предпочтительно использовать функции-члены диапазона для их одноэлементных аналогов. В настоящее время я хочу скопировать все значения на карте (т. е. - мне не нужны ключи) в вектор.
что самый чистый способ сделать это?
11 ответов:
вы не можете легко использовать диапазон здесь, потому что итератор, который вы получаете от карты, относится к паре std::, где итераторы, которые вы использовали бы для вставки в вектор, относятся к объекту типа, хранящегося в векторе, который (если вы отбрасываете ключ) не является парой.
Я действительно не думаю, что это становится намного чище, чем очевидно:
#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) ); }
это решение основано на посте от Михаила Гольдштейна на увеличить список рассылки.
используя лямбды можно выполнить следующее:
{ 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:
for (const auto &s : schemas) names.push_back(s.first);
где схемы является
std::map
и именаstd::vector
.это заполняет массив (имена) с ключами от карты (схемы); изменить
s.first
доs.second
чтобы получить массив значений.
#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)
эта функция называет
unaryOperation
на каждый товар от
вот что я бы сделал.
Также я бы использовал функцию шаблона, чтобы сделать конструкцию 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) ); }
Я думал, что это должно быть
std:: transform( map.begin (), map.конец(), 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);
удивлена, что никто не упомянул самое очевидное решение, используйте конструктор std::vector.
template<typename K, typename V> std::vector<std::pair<K,V>> mapToVector(const std::unordered_map<K,V> &map) { return std::vector<std::pair<K,V>>(map.begin(), map.end()); }