【发布时间】:2011-04-21 19:50:33
【问题描述】:
我有一张一对一的地图。从值中查找键的最佳方法是什么,
即
例如,如果地图是这样的
关键值
a 1
b 2
c 3
d 4
我希望能够找到3对应的键是C。
谢谢!
【问题讨论】:
我有一张一对一的地图。从值中查找键的最佳方法是什么,
即
例如,如果地图是这样的
关键值
a 1
b 2
c 3
d 4
我希望能够找到3对应的键是C。
谢谢!
【问题讨论】:
您对此无能为力。您可以选择使用两张地图,使用来自Boost Multi-Index 库的多键地图,或者进行线性搜索。
更新:最轻量级的开箱即用解决方案似乎是Boost.Bimap,它代表双向地图。
【讨论】:
假设你有一张地图<X,Y>。构建第二个结构,可能是 map<Y*,X*,Deref>,它启用反向查找但避免将存储开销加倍,因为使用指针,无需将每个 X 和 Y 存储两次。第二个结构只是有指向第一个的指针。
【讨论】:
map<X,Y> 中的条目时也要小心,因为指针无效。
最直接的方法是维护一个并行映射,其中值和键是相反的(因为关系是一对一的)。
【讨论】:
另一种解决方案是使用(鲜为人知的?)Boost.Bimap:
Boost.Bimap 是一个双向映射 C++ 库。使用 Boost.Bimap 你 可以在 这两种类型都可以用作键。一种
bimap<X,Y>可以认为是std::map<X,Y>和std::map<Y,X>。学习曲线 如果你知道怎么做,bimap 几乎是平的 使用标准容器。一个伟大的 已经付出了很多努力 映射 STL 的命名方案 在 Boost.Bimap 中。图书馆是 旨在匹配常见的 STL 容器。
【讨论】:
给定一个从键到值的std::map,以下函数将返回一个反向查找表,一个从值到键的std::map。
/// Given a map from keys to values, creates a new map from values to keys
template<typename K, typename V>
static map<V, K> reverse_map(const map<K, V>& m) {
map<V, K> r;
for (const auto& kv : m)
r[kv.second] = kv.first;
return r;
}
【讨论】:
除非地图很大,或者你有其他方式知道线性搜索太慢,否则我会从线性搜索开始:
#include <iostream>
using std::cout;
#include <map>
using std::map;
#include <algorithm>
using std::find_if;
#include <boost/assign/list_of.hpp>
using boost::assign::map_list_of;
typedef map<char, int> Map;
typedef Map::key_type Key;
typedef Map::value_type Pair;
typedef Map::mapped_type Value;
struct finder {
const Value v;
finder(const Value& v) : v(v) {}
bool operator()(const Pair& p) {
return p.second == v;
}
};
Map m = map_list_of('a', 1)('b', 2)('c', 3)('d', 4)('e', 5);
int main() {
Pair v = *find_if(m.begin(), m.end(), finder(3));
cout << v.second << "->" << v.first << "\n";
}
【讨论】:
@Robᵩ 上面使用 lambda 的答案的变体:
map<char, int> m = {{'a', 1}, {'b', 2}, {'c', 3}, {'d', 4}, {'e', 5}};
int findVal = 3;
auto it = find_if(m.begin(), m.end(), [findVal](const Pair & p) {
return p.second == findVal;
});
if (it == m.end()) {
/*value not found*/
cout << "*value not found*";
}
else {
Pair v = *it;
cout << v.second << "->" << v.first << "\n";
}
(感谢@Nawaz 在这里的贡献:https://stackoverflow.com/a/19828596/1650814)
【讨论】:
我知道这是一个很老的问题,但这篇 codeproject 文章 (http://www.codeproject.com/Articles/3016/An-STL-like-bidirectional-map) 是双向映射的一个很好的例子。
这是一个示例程序,展示了它是多么容易:
#pragma warning(disable:4503)
#include "bimap.h"
#include <iostream>
#include <string>
using codeproject::bimap;
int main(void)
{
bimap<int,std::string> bm;
bm[1]="Monday";
bm[2]="Tuesday";
bm[3]="Wednesday";
bm[4]="Thursday";
bm[5]="Friday";
bm[6]="Saturday";
bm[7]="Sunday";
std::cout<<"Thursday occupies place #"<<bm["Thursday"]<<
" in the week (european style)"<<std::endl;
return 0;
}
【讨论】: