C++ unordered_map 其中键也是 unordered_map
C++ unordered_map where key is also unordered_map
我正在尝试使用一个 unordered_map 和另一个 unordered_map 作为键(自定义哈希函数)。我还添加了一个自定义的相等函数,尽管它可能并不需要。
代码没有达到我的预期,但我无法弄清楚发生了什么。出于某种原因,在执行 find() 时没有调用 equal 函数,这正是我所期望的。
unsigned long hashing_func(const unordered_map<char,int>& m) {
string str;
for (auto& e : m)
str += e.first;
return hash<string>()(str);
}
bool equal_func(const unordered_map<char,int>& m1, const unordered_map<char,int>& m2) {
return m1 == m2;
}
int main() {
unordered_map<
unordered_map<char,int>,
string,
function<unsigned long(const unordered_map<char,int>&)>,
function<bool(const unordered_map<char,int>&, const unordered_map<char,int>&)>
> mapResults(10, hashing_func, equal_func);
unordered_map<char,int> t1 = getMap(str1);
unordered_map<char,int> t2 = getMap(str2);
cout<<(t1 == t2)<<endl; // returns TRUE
mapResults[t1] = "asd";
cout<<(mapResults.find(t2) != mapResults.end()); // returns FALSE
return 0;
}
使用 ==
比较两个 std::unordered_map
对象比较映射是否包含相同的键。它无法判断它们是否以相同的顺序包含它们(毕竟这是一个 unordered 映射)。但是,您的 hashing_func
取决于地图中项目的顺序:hash<string>()("ab")
通常不同于 hash<string>()("ba")
。
一个好的起点是每个地图的 hashing_func returns,或者更容易的是 hashing_func 中的字符串构造生成的内容。
对于这种类型更明显正确的散列函数可能是:
unsigned long hashing_func(const unordered_map<char,int>& m) {
unsigned long res = 0;
for (auto& e : m)
res ^ hash<char>()(e.first) ^ hash<int>()(e.second);
return res;
}
首先,相等运算符肯定是必须的,所以你应该保留它。
让我们看看你的无序映射的哈希函数:
string str;
for (auto& e : m)
str += e.first;
return hash<string>()(str);
由于它是一个无序映射,根据定义,迭代器可以以任何顺序迭代无序映射的键。但是,由于哈希函数必须为相同的键生成相同的哈希值,因此此哈希函数在这方面显然会失败。
此外,除了键本身之外,我还希望散列函数还将包含无序映射键的值。我想您可能想这样做——两个无序映射被认为是相同的键,只要它们的键相同,而忽略它们的值。从问题中不清楚你的期望是什么,但你可能需要考虑一下。
我正在尝试使用一个 unordered_map 和另一个 unordered_map 作为键(自定义哈希函数)。我还添加了一个自定义的相等函数,尽管它可能并不需要。
代码没有达到我的预期,但我无法弄清楚发生了什么。出于某种原因,在执行 find() 时没有调用 equal 函数,这正是我所期望的。
unsigned long hashing_func(const unordered_map<char,int>& m) {
string str;
for (auto& e : m)
str += e.first;
return hash<string>()(str);
}
bool equal_func(const unordered_map<char,int>& m1, const unordered_map<char,int>& m2) {
return m1 == m2;
}
int main() {
unordered_map<
unordered_map<char,int>,
string,
function<unsigned long(const unordered_map<char,int>&)>,
function<bool(const unordered_map<char,int>&, const unordered_map<char,int>&)>
> mapResults(10, hashing_func, equal_func);
unordered_map<char,int> t1 = getMap(str1);
unordered_map<char,int> t2 = getMap(str2);
cout<<(t1 == t2)<<endl; // returns TRUE
mapResults[t1] = "asd";
cout<<(mapResults.find(t2) != mapResults.end()); // returns FALSE
return 0;
}
使用 ==
比较两个 std::unordered_map
对象比较映射是否包含相同的键。它无法判断它们是否以相同的顺序包含它们(毕竟这是一个 unordered 映射)。但是,您的 hashing_func
取决于地图中项目的顺序:hash<string>()("ab")
通常不同于 hash<string>()("ba")
。
一个好的起点是每个地图的 hashing_func returns,或者更容易的是 hashing_func 中的字符串构造生成的内容。
对于这种类型更明显正确的散列函数可能是:
unsigned long hashing_func(const unordered_map<char,int>& m) {
unsigned long res = 0;
for (auto& e : m)
res ^ hash<char>()(e.first) ^ hash<int>()(e.second);
return res;
}
首先,相等运算符肯定是必须的,所以你应该保留它。
让我们看看你的无序映射的哈希函数:
string str;
for (auto& e : m)
str += e.first;
return hash<string>()(str);
由于它是一个无序映射,根据定义,迭代器可以以任何顺序迭代无序映射的键。但是,由于哈希函数必须为相同的键生成相同的哈希值,因此此哈希函数在这方面显然会失败。
此外,除了键本身之外,我还希望散列函数还将包含无序映射键的值。我想您可能想这样做——两个无序映射被认为是相同的键,只要它们的键相同,而忽略它们的值。从问题中不清楚你的期望是什么,但你可能需要考虑一下。