map<T,Z> m= .开发者_开发百科..;
vector<T> v;
v.reserve(m.size);
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it)
{
v.push_back(it->first);
}
Is there a nicer 1-line version using some STL function(s)?
edit: not using c++11!
Portable:
struct SelectKey {
template <typename F, typename S>
F operator()(const std::pair<const F, S> &x) const { return x.first; }
};
std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey());
I think some implementations of STL have a non-standard extension called select1st
, which is the equivalent of SelectKey
shown here. As K-Ballo pointed out in the comments, there's also a TR1 version. I like the explicitly-named version as it's easier to see what's going on.
Since there's no need for state, you can get away with slightly less boilerplate by using an actual function rather than a functor:
template <typename F, typename S>
F SelectKey()(const std::pair<const F, S> &x) { return x.first; }
std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey);
If you could use C++11, you could use a lambda, which keeps the selection code close to where it's used:
std::transform(m.cbegin(), m.cend(), std::back_inserter(v),
[](const std::pair<const F, S> &x) { return x.first; });
or even range-based for-loop, which is probably the most elegant and readable:
for(const auto &x : m) {
v.push_back(x.first);
}
Pre C++11, you could use transform and a custom function struct:
template <class K, class V>
struct key_selector : std::unary_function<const std::pair<K, V>&, const K&>
{
const K& operator()(const std::pair<K, V>& element) const
{
return element.first;
}
};
transform(m.begin(), m.end(), back_inserter(v), key_selector<T,Z>());
If you have access to boost or TR1, you can replace key_selector
with mem_fn
transform(m.begin(), m.end(), back_inserter(v), mem_fn(&map<T,Z>::value_type::first));
Post- C++11, you can use lambdas:
transform(m.begin(), m.end(), back_inserter(v), [](const map<T,Z>::value_type& x) {return x.first;});
In C++11, you can use lambda expressions:
typedef std::map< std::string, std::string > map_t;
map_t map;
std::vector< std::string > v;
std::for_each(map.begin(), map.end(), [&v](map_t::value_type const& it)
{
v.push_back(it.first);
});
You can do something along the lines of:
std::transform(m.begin(), m.end(), std::back_inserter(v), FUNCTOR);
Where FUNCTOR depends on what version of the STL or libraries and compilers that you have.
C++11 (lambda)
std::transform(m.begin(), m.end(), std::back_inserter(v), [](map<T,Z>::const_reference a) { return a.first; });
C++11 (std::get)
std::transform(m.begin(), m.end(), std::back_inserter(v), &std::get<0>);
C++ SGI STL has a functor called select1st which can be used
std::transform(m.begin(), m.end(), std::back_inserter(v), select1st);
C++03 (Not C++11) using a functor object like other people have described.
精彩评论