What is the most efficient way of obtaining lists (as a vector
) of the keys and values from an unordered_map
?
For concreteness, suppose the map in question is a unordered_map<string, double>
.
I'd then like to obtain the keys as a vector<string>
, and the values as a vector<double>
.
unordered_map<string, double> um;
vector<string> vs = um.enum_keys();
vector<double> vd = um.enum_values();
I can just iterate across the map and collect the result, but is there a more
efficient method? It would be nice to have a method that also works for regular map,
since I might switch to that.
Okay, here you go:
std::vector<Key> keys;
keys.reserve(map.size());
std::vector<Val> vals;
vals.reserve(map.size());
for(auto kv : map) {
keys.push_back(kv.first);
vals.push_back(kv.second);
}
Efficiency can probably be improved, but there it is. You're operating on two containers though, so there's not really any STL magic that can hide that fact.
As Louis said, this will work for any of the STL map
or set
containers.
Using C++-14 you could also do the following (edited to contain full source):
#include <algorithm>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
using namespace std;
typedef string Key;
typedef int Value;
auto key_selector = [](auto pair){return pair.first;};
auto value_selector = [](auto pair){return pair.second;};
int main(int argc, char** argv) {
// Create a test map
unordered_map<Key, Value> map;
map["Eight"] = 8;
map["Ten"] = 10;
map["Eleven"] = 11;
// Vectors to hold keys and values
vector<Key> keys(map.size());
vector<Value> values(map.size());
// This is the crucial bit: Transform map to list of keys (or values)
transform(map.begin(), map.end(), keys.begin(), key_selector);
transform(map.begin(), map.end(), values.begin(), value_selector);
// Make sure this worked: Print out vectors
for (Key key : keys) cout << "Key: " << key << endl;
for (Value value : values) cout << "Value: " << value << endl;
return 0;
}
I compiled this with the following command:
g++ keyval.cpp -std=c++14 -o keyval
Testing it printed the keys and values as expected.
In STL there is no built-in method to get all keys or values from a map.
There is no different to iterate a unordered map or regular map, the best way is to iterate it and collect key or value to a vector.
You can write a template function to iterate any kind of map.
Joining late, but thought this might be helpful to someone.
Two template functions making use of key_type
and mapped_type
.
namespace mapExt
{
template<typename myMap>
std::vector<typename myMap::key_type> Keys(const myMap& m)
{
std::vector<typename myMap::key_type> r;
r.reserve(m.size());
for (const auto&kvp : m)
{
r.push_back(kvp.first);
}
return r;
}
template<typename myMap>
std::vector<typename myMap::mapped_type> Values(const myMap& m)
{
std::vector<typename myMap::mapped_type> r;
r.reserve(m.size());
for (const auto&kvp : m)
{
r.push_back(kvp.second);
}
return r;
}
}
Usage:
std::map<long, char> mO;
std::unordered_map<long, char> mU;
// set up the maps
std::vector<long> kO = mapExt::Keys(mO);
std::vector<long> kU = mapExt::Keys(mU);
std::vector<char> vO = mapExt::Values(mO);
std::vector<char> vU = mapExt::Values(mU);