通过搜索关键结构的成员值

时间:2016-09-09 06:46:16

标签: c++ lookup unordered-map

我的应用程序有一个像std::unordered_map<my_struct *, std::string>这样的地图,有数十万个元素。 my_struct有一些字符串,向量和其他类型的成员。

在某些步骤中,我需要构建一个新的my_struct,然后查找具有关键字my_struct具有相同成员的地图元素&#39}。像我最近构建的对象中的值。

我唯一可以使用它的方法是使用额外的数字&#34; ID&#34;成员并将std::hash替换为仅从其operator()方法返回的自定义谓词。然而,这不是解决方案。在寻找地图的某些元素时,我无法知道该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;
}

我甚至认为在key_equal构造函数上替换unordered_map我自己的谓词可以解决它,但这也不起作用(我没有得到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 ?

看起来它停在第一个元素上......

第一个输出行很奇怪,即使我没有尝试查找或访问任何元素(std::cout上的评论main()行),也会显示。

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

问题:关于它为什么不起作用的任何建议以及我应该如何对其进行编码以便快速有效地完成我想要的工作?

我想避免遍历所有元素,因为它们中有很多元素(数十万......)并且它们看起来并不是最有效和最快速的方式。

额外问题:我是否应该使用根据test_key成员值构建的字符串作为地图的关键字?我知道代码会更容易,但它会更高效,更快吗? test_key / my_struct的真实实施包含std::map<std::string, std::string> s,std::vector<std::string>和许多其他类型的成员(已经做了很多工作来比较其中两个结构)和将它全部放在一个字符串中将很难构建和解析...我知道我必须对它进行基准测试,但我想得到一些提示。

1 个答案:

答案 0 :(得分:1)

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

您需要选择另一种数据结构 - 可以根据您要搜索的内容进行排序。它可以是一个独立的数据结构,也可以是一个并行的数据结构 - 可能是你的unordered_map,但你必须拥有一个由你想要搜索的内容组织的东西,或者你将要进行详尽的搜索。