从unordered_map获取键和值列表

Fah*_*tha 53 c++ unordered-map vector std c++11

vector从a获取键和值的列表(作为a )的最有效方法是unordered_map什么?

具体来说,假设有问题的地图是一个unordered_map<string, double>.然后我想把键作为a vector<string>,并将值作为a vector<double>.

unordered_map<string, double> um;

vector<string> vs = um.enum_keys();
vector<double> vd = um.enum_values(); 
Run Code Online (Sandbox Code Playgroud)

我可以遍历地图并收集结果,但是有更有效的方法吗?有一个方法也适用于常规地图会很好,因为我可能会切换到那个.

Kei*_*yne 62

好的,你走了:

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);  
} 
Run Code Online (Sandbox Code Playgroud)

效率可能会提高,但确实如此.你在两个容器上操作,所以没有任何STL魔法可以隐藏这个事实.

正如路易斯所说,这适用于任何STL mapset容器.

  • 我会在这里使用`auto &`而不是`auto`来避免对的不必要的副本(如果它们是结构,则为底层的第一/第二成员).并且它不适用于`set`容器,因为它们的`value_type`不是`std :: pair <K,V>`而是Key/Val类型本身. (3认同)
  • 好的,我想没有什么比迭代地图更好的了.我不认识你正在使用的语法.什么`(auto kv:map)`表示.我原本期望在地图元素上进行迭代(即循环). (2认同)
  • 保留可以提高效率,但不会比这更快或更容易. (2认同)

Mar*_*enn 12

使用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;
}
Run Code Online (Sandbox Code Playgroud)

我用以下命令编译了这个:

g++ keyval.cpp -std=c++14 -o keyval
Run Code Online (Sandbox Code Playgroud)

测试它按预期打印键和值.

  • lambas 不应该引入任何开销,它们(像任何其他函子一样)可以内联到 `transform` 循环中。但是当使用 `auto` 时一定要记住它会推导出值类型,所以那些基于范围的 for 循环会引入一些副本。你可以使用 `const auto&amp;` 而不是普通的 `auto`,在那里它是有意义的。 (2认同)