STL의 벡터에 맵 값 복사
현재 효과적인 STL을 통해 작업 중입니다. 항목 5는 일반적으로 단일 요소 대응에 대해 범위 멤버 함수를 사용하는 것이 바람직하다는 것을 제안합니다. 현재 맵의 모든 값 (예 : 키가 필요하지 않음)을 벡터에 복사하고 싶습니다.
이를 수행하는 가장 깨끗한 방법은 무엇입니까?
지도에서 얻은 반복기가 std :: pair를 참조하기 때문에 여기서 범위를 쉽게 사용할 수 없습니다. 여기서 벡터에 삽입하는 데 사용할 반복자는 벡터에 저장된 유형의 객체를 참조합니다. (키를 버리는 경우) 쌍이 아닙니다.
나는 그것이 명백한 것보다 훨씬 깨끗하다고 생각하지 않습니다.
#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) );
}
이 솔루션은 부스트 메일 링리스트 에있는 Michael Goldshteyn의 게시물을 기반으로 합니다 .
오래된 질문, 새로운 답변. C ++ 11에는 멋진 새로운 for 루프가 있습니다.
for (const auto &s : schemas)
names.push_back(s.first);
여기서 스키마는 a std::map이고 이름은 std::vector.
이렇게하면 배열 (이름)이 맵 (스키마)의 키로 채워집니다. 변화 s.first하는 s.second값의 배열을 얻을.
람다를 사용하면 다음을 수행 할 수 있습니다.
{
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); });
}
#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모든 항목을 호출 합니다 . 작업 값은에 저장됩니다 .inputIteratorbeginInputRangeendInputRangeoutputIterator
전체 맵을 통해 작업하려면 map.begin () 및 map.end ()를 입력 범위로 사용합니다. 벡터에 맵 값을 저장하고 싶으므로 벡터에 back_inserter를 사용해야합니다 : back_inserter(your_values_vector). back_inserter는 주어진 (파레 미터로) 컬렉션의 끝에 새 요소를 푸시하는 특수 outputIterator입니다. 마지막 매개 변수는 unaryOperation이며 하나의 매개 변수 (inputIterator의 값) 만 사용합니다. 따라서 lambda :를 사용할 수 있습니다. [](auto &kv) { [...] }여기서 & kv는 맵 항목의 쌍에 대한 참조 일뿐입니다. 따라서 맵 항목의 값만 반환하려면 kv.second를 반환하면됩니다.
[](auto &kv) { return kv.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)
);
}
나는 그것이되어야한다고 생각했다
std::transform( map.begin(), map.end(),
std::back_inserter(vec),
boost::bind(&MapT::value_type::first,_1) );
한 가지 방법은 functor를 사용하는 것입니다.
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);
We should use the transform function from STL algorithm, the last parameter of transform function could be a function object, function pointer or a lambda function that convert item of map to item of vector. This case map have items have type pair that need to convert to item that has int type for vector. Here is my solution that I use lambda function:
#include <algorithm> // for std::transform
#include <iterator> // for back_inserted
// Map of pair <int, string> need to convert to vector of string
std::map<int, std::string> mapExp = { {1, "first"}, {2, "second"}, {3, "third"}, {4,"fourth"} };
// vector of string to store the value type of map
std::vector<std::string> vValue;
// Convert function
std::transform(mapExp.begin(), mapExp.end(), std::back_inserter(vValue),
[](const std::pair<int, string> &mapItem)
{
return mapItem.second;
});
Surprised nobody has mentioned the most obvious solution, use the std::vector constructor.
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());
}
참고URL : https://stackoverflow.com/questions/771453/copy-map-values-to-vector-in-stl
'developer tip' 카테고리의 다른 글
| Maven에서 PostgreSQL 드라이버를 종속성으로 추가하는 방법은 무엇입니까? (0) | 2020.11.01 |
|---|---|
| Swift에서 간단한 페이드 인 애니메이션을 만드시겠습니까? (0) | 2020.11.01 |
| django @login_required 수퍼 유저 용 데코레이터 (0) | 2020.10.31 |
| Android Studio에서 수동으로 ADB를 다시 시작하는 방법 (0) | 2020.10.31 |
| 업데이트 패널 포스트 백 후 JavaScript 콜백을 실행하는 방법은 무엇입니까? (0) | 2020.10.31 |