在 std::set 上按名称查找对象

Lookup objects by name on std::set

本文关键字:查找 对象 std set      更新时间:2023-10-16

我需要将一些对象存储在std:set(或任何其他类型的查找表)中,并按名称搜索它们。

例如,假设我有一个类似(伪代码)的类:

class Person
{
    std::string mName;
    int mAge;
    ... //etc
};

我想将其存储在容器上并按名称搜索对象。我不能将它们插入 std::set 上,因为据我所知,我必须构造一个完整的对象进行搜索。

我的第二个是使用像 std::map 这样的 std::map,但是,我需要为此复制名称,我不想复制密钥。

有没有办法将这种对象存储在 std::set(或任何其他容器)中并通过键(而不是对象)进行搜索?

谢谢

请查看 boost::intrusive containers,特别是 boost::intrusive::set。

换来的是 Item 类的一些丑陋化,带来了极大的灵活性。发生 Uglization 是因为 Item 必须派生自某个类,或者它必须声明一个特殊的成员变量来存储树链接。不过,这一切都包装得很好。

关于特定请求,boost::intrusive::set 允许

  • 重用 mName 作为密钥(与 std::set 不同)
  • 通过字符串查找 Person (与 std::set 不同,不需要构造 Person 来执行查找)
因此,

您可以使用find_if来实现此目的:

struct find_by_name {
    find_by_name(const std::string & name) : name(name) {}
    bool operator()(const Person & person) {
        return person.name == name;
    }
private:
    std::string name;
};
// in your code
std::set<Person>::iterator result = std::find_if(people.begin(), people.end(), 
                                              find_by_name("Ben"));
if(result != people.end()) {
    // we found something
}
else {
    // no match
}

通过这种方式,您可以仅基于生成的字符串(在结构中)进行搜索,并且它的适应性很强,您可以使用任何字符串对其进行初始化,也可以使用它在任何实现迭代器的容器中搜索person

您可以使用 std::find_if ,例如,如果您有std::set<Person> people

auto match = std::find_if(people.begin(), people.end(), [](const Person& foo){return foo.mName == "Bob";});
if (match != people.end())
{
    std::cout << "Found Bob!"
}

因此,您不需要创建一个完整的Person对象,例如,只需创建一个与它们的名称匹配的std::string