77

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

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

4

5 回答 5

80

好的,给你:

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 魔法可以隐藏这一事实。

正如路易斯所说,这将适用于任何 STLmapset容器。

于 2011-12-13T03:41:44.417 回答
19

使用 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

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

于 2015-11-19T02:20:14.847 回答
4

在 STL 中,没有内置方法可以从映射中获取所有键或值。

迭代无序映射或常规映射没有什么不同,最好的方法是迭代它并将键或值收集到向量。

您可以编写一个模板函数来迭代任何类型的地图。

于 2011-12-13T03:34:04.223 回答
1

加入晚了,但认为这可能对某人有帮助。使用和
的两个模板函数。key_typemapped_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);
于 2015-11-26T15:00:41.850 回答
0

类似于@Keith Layne 的回答,但保留是在一行中完成的;并且 for 循环使用引用(而不是按每个条目的值复制它)并将其设为 const。但是如果可以使用 C++14,那么@Marius Renn 的答案应该会更好。

std::map<long, char> mO;

// populate the mO

std::vector<long> keys(mO.size());
std::vector<char> vals(mO.size());

for(const auto &kv : mO) {
    keys.push_back(kv.first);
    vals.push_back(kv.second);  
} 
于 2022-01-22T23:30:12.240 回答