web-dev-qa-db-ja.com

unordered_mapからキーと値のリストを取得する

unordered_mapからキーと値のリストを(vectorとして)取得する最も効率的な方法は何ですか?

具体的には、問題のマップが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(); 

マップ全体を反復処理して結果を収集できますが、より効率的な方法はありますか?私はそれに切り替えるかもしれないので、通常のマップでも機能するメソッドがあるといいでしょう。

51
Faheem Mitha

さて、ここに行きます:

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

効率はおそらく改善できますが、改善されています。ただし、2つのコンテナを操作しているため、その事実を隠すことができるSTLマジックは実際にはありません。

Louisが言ったように、これはSTL mapまたはsetコンテナのいずれでも機能します。

59
Keith Layne

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

それをテストすると、期待どおりにキーと値が印刷されました。

11
Marius Renn

STLには、マップからすべてのキーまたは値を取得する組み込みメソッドはありません。

順序付けられていないマップまたは通常のマップを繰り返すことには違いはありません。最善の方法は、それを繰り返して、キーまたは値をベクトルに収集することです。

テンプレート関数を作成して、あらゆる種類のマップを反復処理できます。

2
Louis

遅く参加したが、これは誰かに役立つかもしれないと思った。
key_typeおよびmapped_typeを使用する2つのテンプレート関数。

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