Obtención de la lista de claves y valores del mapa desordenado


¿Cuál es la forma más eficiente de obtener listas (como un vector) de las claves y valores de un unordered_map?

Para concreción, supongamos que el mapa en cuestión es un unordered_map<string, double>. Entonces me gustaría obtener las claves como un vector<string>, y los valores como un vector<double>.

unordered_map<string, double> um;

vector<string> vs = um.enum_keys();
vector<double> vd = um.enum_values(); 

Solo puedo recorrer el mapa y recoger el resultado, pero ¿hay más método eficiente? Sería bueno tener un método que también funciona para el mapa regular, ya que podría cambiar a eso.

Author: Xeo, 2011-12-13

4 answers

Bien, aquí tienes:

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

La eficiencia probablemente se puede mejorar, pero ahí está. Estás operando en dos contenedores sin embargo, así que no hay realmente ninguna magia STL que pueda ocultar ese hecho.

Como dijo Louis, esto funcionará para cualquiera de los contenedores STL map o set.

 52
Author: Keith Layne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-13 17:00:29

Usando C++-14 también podría hacer lo siguiente (editado para contener el código fuente completo):

#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;
}

Compilé esto con el siguiente comando:

g++ keyval.cpp -std=c++14 -o keyval

La prueba imprimió las claves y los valores como se esperaba.

 9
Author: Marius Renn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-26 16:45:12

En STL no hay un método integrado para obtener todas las claves o valores de un mapa.

No hay diferencia para iterar un mapa desordenado o un mapa regular, la mejor manera es iterarlo y recopilar la clave o el valor de un vector.

Puede escribir una función de plantilla para iterar cualquier tipo de mapa.

 2
Author: Louis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-13 03:34:04

Unirse tarde, pero pensé que esto podría ser útil para alguien.
Dos funciones de plantilla que hacen uso de key_type y 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;
    }
}

Uso:

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);
 0
Author: elimad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-26 15:00:41