Obtaining list of keys and values from unordered_map

C++VectorC++11StdUnordered Map

C++ Problem Overview


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.

C++ Solutions


Solution 1 - C++

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.

Solution 2 - C++

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.

Solution 3 - C++

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.

Solution 4 - C++

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);

Solution 5 - C++

Similar to @Keith Layne answer, but reserve is done in one line; And the for loop is using reference (instead of copying it by value each entry) and making it const. But if C++14 can be used then @Marius Renn answer should be better.

std::map<long, char> mO;

// populate the mO

std::vector<long> keys(mO.size());
std::vector<char> vals(mO.size());

for(const auto &kv : mO) {
    keys.push_back(kv.first);
    vals.push_back(kv.second);  
} 

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionFaheem MithaView Question on Stackoverflow
Solution 1 - C++Keith LayneView Answer on Stackoverflow
Solution 2 - C++Marius RennView Answer on Stackoverflow
Solution 3 - C++LouisView Answer on Stackoverflow
Solution 4 - C++elimadView Answer on Stackoverflow
Solution 5 - C++Anton KrugView Answer on Stackoverflow