How to retrieve all keys (or values) from a std::m

2020-01-23 15:18发布

This is one of the possible ways I come out:

struct RetrieveKey
{
    template <typename T>
    typename T::first_type operator()(T keyValuePair) const
    {
        return keyValuePair.first;
    }
};

map<int, int> m;
vector<int> keys;

// Retrieve all keys
transform(m.begin(), m.end(), back_inserter(keys), RetrieveKey());

// Dump all keys
copy(keys.begin(), keys.end(), ostream_iterator<int>(cout, "\n"));

Of course, we can also retrieve all values from the map by defining another functor RetrieveValues.

Is there any other way to achieve this easily? (I'm always wondering why std::map does not include a member function for us to do so.)

16条回答
我只想做你的唯一
2楼-- · 2020-01-23 15:30

Based on @rusty-parks solution, but in c++17:

std::map<uint32_t, uint32_t> items;
std::vector<uint32_t> itemKeys;
for (const auto& [key, std:ignore] : items) {
  itemKeys.emplace_back(key);
}
查看更多
家丑人穷心不美
3楼-- · 2020-01-23 15:31

@DanDan's answer, using C++11 is:

using namespace std;
vector<int> keys;

transform(begin(map_in), end(map_in), back_inserter(keys), 
            [](decltype(map_in)::value_type const& pair) {
    return pair.first;
}); 

and using C++14 (as noted by @ivan.ukr) we can replace decltype(map_in)::value_type with auto.

查看更多
别忘想泡老子
4楼-- · 2020-01-23 15:31

Also, if you have Boost, use transform_iterator to avoid making a temporary copy of the keys.

查看更多
我只想做你的唯一
5楼-- · 2020-01-23 15:33

While your solution should work, it can be difficult to read depending on the skill level of your fellow programmers. Additionally, it moves functionality away from the call site. Which can make maintenance a little more difficult.

I'm not sure if your goal is to get the keys into a vector or print them to cout so I'm doing both. You may try something like this:

map<int, int> m;
vector<int> v;
for(map<int,int>::iterator it = m.begin(); it != m.end(); ++it) {
  v.push_back(it->first);
  cout << it->first << "\n";
}

Or even simpler, if you are using Boost:

map<int,int> m;
pair<int,int> me; // what a map<int, int> is made of
vector<int> v;
BOOST_FOREACH(me, m) {
  v.push_back(me.first);
  cout << me.first << "\n";
}

Personally, I like the BOOST_FOREACH version because there is less typing and it is very explicit about what it is doing.

查看更多
兄弟一词,经得起流年.
6楼-- · 2020-01-23 15:35

You can use the versatile boost::transform_iterator. The transform_iterator allows you to transform the iterated values, for example in our case when you want to deal only with the keys, not the values. See http://www.boost.org/doc/libs/1_36_0/libs/iterator/doc/transform_iterator.html#example

查看更多
Deceive 欺骗
7楼-- · 2020-01-23 15:38

Bit of a c++11 take:

std::map<uint32_t, uint32_t> items;
std::vector<uint32_t> itemKeys;
for (auto & kvp : items)
{
    itemKeys.emplace_back(kvp.first);
    std::cout << kvp.first << std::endl;
}
查看更多
登录 后发表回答