2011-12-13 20 views
45

Qual è il modo più efficace per ottenere elenchi (come vector) di chiavi e valori da un unordered_map?Ottenere l'elenco di chiavi e valori da unordered_map

Per la concretezza, supponiamo che la mappa in questione sia unordered_map<string, double>. Vorrei quindi ottenere le chiavi come vector<string> e i valori come vector<double>.

unordered_map<string, double> um; 

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

posso solo iterare attraverso la mappa e raccogliere il risultato, ma c'è un metodo più efficiente? Sarebbe bello avere un metodo che funzioni anche per la mappa regolare, dato che potrei passare a quello.

+0

Guardando il progetto di norma, non vedo un modo semplice per ottenere quello che vuoi, ma io potrebbe essere manca qualcosa. Si potrebbe dire 'std :: vector > v (map.begin(), map.end()); 'che dovrebbe darti un vettore di coppie chiave-valore. –

+0

@ keith.layne: Sto cercando vettori separati per chiavi e valori. –

+0

Come ho già detto, non c'è niente di integrato in questo. Vedi sotto. –

risposta

47

Va bene, qui si va:

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

efficienza può probabilmente essere migliorata, ma è così. Stai operando su due contenitori, quindi non c'è davvero alcuna magia STL che possa nascondere questo fatto.

Come ha detto Louis, questo funzionerà per tutti i container STL map o set.

+1

Ok, sO suppongo che non ci sia niente di meglio che scorrere sulla mappa allora. Non riconosco la sintassi che stai usando. Cosa indica '(auto kv: map)'. Mi sarei aspettato solo un'iterazione (vale a dire per il ciclo) sugli elementi della mappa. –

+1

@FaheemMitha Questo è il nuovo C++ 11 per il ciclo. Fa esattamente quello che sembra, e combinato con 'auto' rende le cose un po 'più ordinate. 'auto' ti salva dal dover scrivere esplicitamente il tipo di kv. Ci sono diversi modi per realizzare essenzialmente la stessa cosa includendo un ciclo for sugli iteratori, 'for_each' con un lambda, ecc. Dato che hai menzionato' unordered_map', ho pensato che stavi usando C++ 11. –

+0

Credo di esserlo, ma non sono molto familiare con il nuovo standard. Grazie. –

2

In AWL non esiste un metodo incorporato per ottenere tutte le chiavi oi valori da una mappa.

Non c'è alcun modo diverso per iterare una mappa non ordinata o una mappa regolare, il modo migliore è quello di iterarlo e raccogliere la chiave o il valore di un vettore.

È possibile scrivere una funzione di modello per iterare qualsiasi tipo di mappa.

6

con C++ - 14 si potrebbe anche fare quanto segue (a cura di contenere sorgente 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; 
} 

ho compilato questo con il seguente comando:

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

testarlo stampato le chiavi e valori come previsto.

+0

Puoi spiegarlo ancora – Whitecat

+0

Potresti scrivere un esempio autosufficiente che può essere compilato? Inoltre, se si potesse menzionare quale compilatore utilizzare e fornire una riga di comando da utilizzare per compilarlo, sarebbe utile. Grazie. –

+0

Inoltre, quali sono 'Key' e' Value' e 'um' qui? Non li hai definiti. Forse stai usando la definizione della domanda, ovvero "unordered_map um;", ma in tal caso, dovresti menzionarlo di nuovo qui, a prescindere. –

0

Unirsi tardi, ma ho pensato che questo potesse essere utile a qualcuno.
Due funzioni modello che utilizzano key_type e 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); 
Problemi correlati