通过关键点向量从地图中获取地图

Get map from map by vector of keys

本文关键字:地图 获取 向量 关键点      更新时间:2023-10-16

我想知道,是否有std::map的函数可以接收由键的std::向量定义的子映射。就像std::map.at(key)函数一样,但有一个std::向量键。我知道我可以迭代映射并将映射对添加到新映射中,但我想知道是否有内置函数,或者是否有更快的方法来获得子映射。

示例代码:

std::map<std::string, int> map = {{"a", 1}, {"b", 2}, {"c", 3}, {"d", 4}, {"e", 5}};
std::vector<std::string> keys = {"a", "c", "d"};
// using iteration:
std::map<std::string, int> new_map;
for(auto it = map.begin(); it != map.end(); ++it){
if(std::find(keys.begin(), keys.end(), it->first) != keys.end()){
new_map.insert(*it);
}
}
// new_map should be {{"a",1}, {"c",3}, {"d",4}}
// What I am hoping to find is something like:
new_map = map.at(keys);
//resulting in the same new_map {{"a",1}, {"c",3}, {"d",4}}.

有没有这样的函数,或者总的来说,有没有比在整个地图上迭代并每次使用find函数更聪明的方法(我知道我可以在向量上迭代,但这没有多大区别,或者说有没有?(。

我知道我可以迭代向量,但这没有多大区别,是吗?

这确实有区别,因为按顺序迭代矢量通常比映射更快(矢量数据在内存中是本地的,映射元素不是本地的(,并且在映射中查找元素比在矢量中查找元素更快(对于未排序的矢量,O(log(N))O(N)(。

假设映射中有M元素,向量中有N键,则方法为O( M * N),而交换迭代和查找仅为O( N * log(M))。这只考虑了find的复杂性。考虑迭代更为复杂,因为它在很大程度上依赖于缓存。

否则,我认为你的方法是好的。我不知道有什么算法能让你的代码更简洁或更具表达力。

PS你可能会认为这是措辞上的挑剔,但由于人们经常过度思考问题,我会提到它:"更聪明的方法"并不总是"更好的方法"。不要太聪明。大多数算法都可以用简单的循环代替,但通常认为它们比手写循环更具表达力和可读性。当手头没有解决问题的算法时,试图将某些内容压缩到算法中,通常会导致代码可读性和表达性降低。如果有人找到了一个可以在这里使用的算法,我会收回这个PS:P 中的所有内容

我也会考虑使用std::copy_if算法。它在源代码中没有保存太多字符,但它更明确:

std::map<std::string, int> map = {{"a", 1}, {"b", 2}, {"c", 3}, {"d", 4}, {"e", 5}};
std::unordered_set<std::string> keys = {"a", "c", "d"};
std::map<std::string, int> new_map;
std::copy_if(map.begin(), map.end(),
std::inserter(new_map, new_map.end()),
[&keys](const auto& e){ return keys.find(e.first) != keys.end(); });

现场演示。


在C++20中,我们将能够更紧凑地编写:

std::copy_if(map.begin(), map.end(),
std::inserter(new_map, new_map.end()),
[&keys](const auto& e){ return keys.contains(e.first); });

从formerlykknownas_463035818的答案开始(因此在keys上而不是在map上迭代(,在我看来,"算法方式"(意思是:使用<algorithm>标头中的标准算法(可能是使用std::transform()

std::transform(keys.cbegin(), keys.cend(),
std::inserter(new_map, new_map.end()),
[&](auto const & k) -> std::pair<std::string, int>
{ return {k, map[k]}; });

但是(IMHO(比旧的环路可读性要好得多

for ( auto const & k : keys )
new_map[k] = map[k];

非主题未请求的建议:不要对"std::map"变量使用"map"(与类的名称相同,忽略命名空间(。也许有效,但没有人添加using std;。。。但为什么要挑战命运呢?