Получение списка ключей и значений из unordered_map - PullRequest
51 голосов
/ 13 декабря 2011

Каков наиболее эффективный способ получения списков (как vector) ключей и значений из unordered_map?

Для конкретности предположим, что рассматриваемая карта является unordered_map<string, double>. Затем я хотел бы получить ключи как vector<string>, а значения как vector<double>.

unordered_map<string, double> um;

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

Я могу просто пройтись по карте и собрать результат, но есть ли еще эффективный метод? Было бы неплохо иметь метод, который также работает для обычной карты, так как я мог бы перейти на это.

Ответы [ 4 ]

58 голосов
/ 13 декабря 2011

Хорошо, вот, пожалуйста:

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

Эффективность, вероятно, можно улучшить, но это так. Вы работаете с двумя контейнерами, так что на самом деле нет никакой магии STL, которая могла бы скрыть этот факт.

Как сказал Луи, это будет работать для любого из контейнеров STL map или set.

10 голосов
/ 19 ноября 2015

Используя C ++ - 14, вы также можете сделать следующее (отредактировано, чтобы содержать полный исходный код):

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

Я скомпилировал это с помощью следующей команды:

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

Тестирование напечатаноключи и значения, как и ожидалось.

2 голосов
/ 13 декабря 2011

В STL нет встроенного метода для получения всех ключей или значений из карты.

Нет ничего иного для итерации неупорядоченной карты или регулярной карты, лучший способ - итерировать и собирать ееключ или значение для вектора.

Вы можете написать шаблонную функцию для итерации любого вида карты.

0 голосов
/ 26 ноября 2015

Поздно присоединился, но подумал, что это может быть полезно для кого-то.
Две шаблонные функции, использующие key_type и 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;
    }
}

Использование:

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