webentwicklung-frage-antwort-db.com.de

Abrufen einer Liste von Schlüsseln und Werten aus "unordered_map"

Was ist die effizienteste Methode, um Listen (als vector) der Schlüssel und Werte aus einem unordered_map?

Angenommen, die betreffende Karte ist ein unordered_map<string, double>. Ich möchte dann die Schlüssel als vector<string> und die Werte als vector<double>.

unordered_map<string, double> um;

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

Ich kann einfach über die Karte iterieren und das Ergebnis sammeln, aber gibt es eine effizientere Methode? Es wäre schön, eine Methode zu haben, die auch für reguläre Karten funktioniert, da ich vielleicht dazu wechseln würde.

51
Faheem Mitha

Okay, los geht's:

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

Effizienz kann wahrscheinlich verbessert werden, aber da ist es. Sie arbeiten jedoch mit zwei Containern, sodass es keine STL-Magie gibt, die diese Tatsache verbergen könnte.

Wie Louis sagte, funktioniert dies für jeden der STL-Container map oder set.

59
Keith Layne

Mit C++ - 14 können Sie auch Folgendes tun (bearbeitet, um den vollständigen Quellcode zu enthalten):

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

Ich habe dies mit folgendem Befehl kompiliert:

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

Beim Testen wurden die Schlüssel und Werte wie erwartet gedruckt.

11
Marius Renn

In AWL gibt es keine integrierte Methode, um alle Schlüssel oder Werte von einer Karte abzurufen.

Es ist nicht anders, eine ungeordnete Karte oder eine reguläre Karte zu iterieren. Der beste Weg ist, sie zu iterieren und Schlüssel oder Wert für einen Vektor zu sammeln.

Sie können eine Vorlagenfunktion schreiben, um jede Art von Karte zu iterieren.

2
Louis

Ich bin spät dran, dachte aber, dass dies für jemanden hilfreich sein könnte.
Zwei Template-Funktionen mit key_type und 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;
    }
}

Verwendung:

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
elimad