通过搜索键结构的成员值来查找unordered_map元素

Find unordered_map elements by searching for key struct's members values

本文关键字:查找 unordered 元素 map 成员 搜索 结构      更新时间:2023-10-16

我的应用程序有一个像std::unordered_map<my_struct *, std::string>这样的映射,它有成千上万个元素。my_struct有一些字符串、向量和其他类型的成员。

在某些步骤中,我需要构建一个新的my_struct,然后寻找具有与我最近构建对象中具有相同成员值的键my_struct的映射元素。

我唯一能让它工作的方法是使用一个额外的数字"ID"成员,并用自定义谓词替换std::hash,该谓词只是从operator()方法返回它。然而,这不是一个解决方案。在寻找map的某些元素时,我无法知道ID。

这是我写的测试代码(test_key = my_struct):
#include <unordered_map>
#include <string>
#include <iostream>
struct test_key
{
        std::size_t id; //can't exist in my application
        std::string test_str1;
        std::string test_str2;
        unsigned int test_uint;
        test_key(std::size_t id_, std::string test_str1_, std::string test_str2_, unsigned int test_uint_)
                : id(id_), test_str1(test_str1_), test_str2(test_str2_), test_uint(test_uint_)
        {}
};
struct test_key_hasher
{
        std::size_t operator() (test_key* const& tst_k) const
        {
                return tst_k->id;
        }
};

int main()
{
        std::unordered_map<test_key *, std::string, test_key_hasher> values;
        test_key *tst_k1, *tst_k2, *tst_k3, *tst_k4, *tst_lk;
        tst_k1 = new test_key(1, "something 11", "something 12", 1112);
        tst_k2 = new test_key(2, "something 21", "something 22", 2122);
        tst_k3 = new test_key(3, "something 31", "something 32", 3132);
        tst_k4 = new test_key(4, "something 41", "something 42", 4142);
        values.emplace(tst_k1, "first thing");
        values.emplace(tst_k2, "second thing");
        values.emplace(tst_k3, "third thing");
        values.emplace(tst_k4, "fourth thing");
        tst_lk = new test_key(3, "something 31", "something 32", 3132); //there is no way I could know ID 3 here
        std::cout << values[tst_lk] << std::endl; //Expected output: third thing
        delete tst_k1;
        delete tst_k2;
        delete tst_k3;
        delete tst_k4;
        delete tst_lk;
}

我甚至认为在unordered_map构造函数上替换key_equal为我自己的谓词可以解决它,但这也不起作用(我没有得到map的值作为输出)。我写的key_equal替换谓词是:

struct test_key_comp
{
        bool operator() (test_key* const& tst_k1, test_key* const& tst_k2) const
        {
                //debug
                std::cout << tst_k1->test_str1 << " == " << tst_k2->test_str1 << " ?" << std::endl;
                return tst_k1->test_str1 == tst_k2->test_str1
                        && tst_k1->test_str2 == tst_k2->test_str2
                        && tst_k1->test_uint == tst_k2->test_uint;
        }
};

然后我的地图看起来像std::unordered_map<test_key *, std::string, std::hash<test_key *>, test_key_comp>

当使用test_key_comp代替默认的key_equal时,上面的代码给出了以下输出:

something 21 == something 11 ?
something 31 == something 11 ?

看起来像在第一个元素上停止…

第一个输出行非常奇怪,即使我不试图查找或访问任何元素(在main()上注释std::cout行),它也会出现。

我也尝试过使用find()方法,但结果与operator[]at()相同。

问题:关于它为什么不起作用以及我应该如何编码它以快速有效的方式完成我想要的东西的任何建议?

我想避免循环遍历所有元素,因为它们会有很多(成千上万…),这看起来不是最有效和最快的方法。

额外问题:也许我应该使用从test_key的成员值构建的字符串作为映射的关键?我知道这样会更容易编写代码,但是这样会更高效、更快吗?test_key/my_struct的真正实现有std::map<std::string, std::string> s, std::vector<std::string> s和许多其他类型的成员(已经有很多工作来比较这两个结构体),把它都放在一个字符串内很难构建和解析…我知道我必须对它进行基准测试,但我想得到一些提示。

您想通过哈希以外的其他内容高效地查找哈希映射中的内容吗?这不是他们的工作方式。

你需要选择另一个数据结构——一个可以按你想要搜索的东西排序的数据结构。它可以是一个独立的数据结构,也可以是一个并行的——可能是你的unordered_map,但你必须有一些东西是根据你想要搜索的东西组织的否则你就会做一个穷举搜索