C++ 在具有非键类型的集合中进行有效搜索

C++ 在具有非键类型的集合中进行有效搜索,c++,stl,C++,Stl,我有一个类似的数据结构,如下所示: struct Data { std::string id; Blob data; }; 现在,我可以使用std::map来存储结构并按ID进行搜索,但我正在寻找一种方法,用std::set实现同样的效果(因为我实际上不需要将ID和结构分开) std::set::find当然会将键类型作为参数,所以我可以这样做(使用适当的构造函数): set x;x、 查找(数据(“某些id”); 但如果可能的话,我想避免这种情况。它需要有一个允许ID不带数据的构造函数,而

我有一个类似的数据结构,如下所示:

struct Data { std::string id; Blob data; };
现在,我可以使用
std::map
来存储结构并按ID进行搜索,但我正在寻找一种方法,用
std::set
实现同样的效果(因为我实际上不需要将ID和结构分开)

std::set::find
当然会将键类型作为参数,所以我可以这样做(使用适当的构造函数):

set x;x、 查找(数据(“某些id”);
但如果可能的话,我想避免这种情况。它需要有一个允许ID不带数据的构造函数,而且我不太喜欢构造一个对象,只是把它用作搜索键


所以我的问题是:有更好的方法吗?

更好的方法是让
id
索引
数据。但既然您不想这样做,请尝试使用
std::find_if(x.first(),x.end(),--predicate-->/code>,其中predicate是一个函数对象或lambda函数谓词,它将
数据
与指定的
id

,除非开销明显不可接受,否则我选择
std::map
,或者可能是
std::map
,假设您无法访问本地提供共享ptr的编译器。

加入一些构造函数和
操作符,如果您不反对使用,则可以使这一过程非常简单,而不会添加任何不必要的低效。下面是一个有效创建
数据
对象的
的示例,该对象键入
数据::id
的值:

#包括
#包括
#包括
#包括
#包括
#包括
命名空间bmi=boost::multi_索引;
typedef char const*Blob;
结构数据
{
std::字符串id;
Blob数据;
void display()常量{std::cout数据集;
int main()
{
数据d1={“某些_id”,nullptr};
数据d2={“某些其他id”,nullptr};
数据集;
套。插入(d1);
套。插入(d2);
set.find(“some_id”)->display();
//对于exposition,find实际上返回一个迭代器
DataSet::const_iterator iter=set.find(“some_other_id”);
if(iter!=set.end())
iter->display();
//set semantics--new_added在这里为false,因为
//容器已包含id为“some_id”的数据对象
数据d3={“some_id”,“blob Data”};
bool const new_added=set.insert(d3).second;

std::cout我意识到这个问题是在可能之前提出的,但是:


从C++14开始,可以在一个集合内搜索,而无需创建密钥类型的实例,并附加获取模板密钥的重载。

这不会降低搜索的线性复杂性吗?@Let_Me_Be:Yeap,这就是为什么应该使用
std::map
。@MooingDuck这到底有什么帮助?std::set::find\lower_bound是对数而不是线性的。我忘了你是在没有创建
数据
实例来搜索的情况下尝试这样做的。只需使用
映射
。将id存储两次并没有什么错。如果它困扰你,请将其设置为
映射
,并从inser的
结构
中提取这两个字段初始化时间。我已经搜索了标准。您可以使用非数据键,但它将使用O(n)迭代器高级(日志(n)比较)。或者您可以使用O(日志(n))的数据键。不幸的是,如果您不想使用任何一个,则必须使用std::map。可能的重复项
set<Data> x; x.find(Data("some_id"));
 struct Data { 
    std::string id; 
    Blob data; 

    Data(const char* r) : id(r), data() {}
    bool operator<(const Data & r) const {return id<r.id;}

    // rest not needed for demo, but handy
    Data() : id(), data() {}
    Data(std::string&& r) : id(std::move(r)), data() {}
    Data(const std::string& r) : id(r), data() {}
    Data(Data && r) : id(r.id), data(r.data) {}
    Data(const Data & r) : id(r.id), data(r.data) {}
    ~Data() {} 
};

int main() {
    std::set<Data> x;
    x.insert("Apple");
    x.insert("Banana");
    x.insert("Orange");
    x.insert("Grape");

    std::set<Data>::iterator i = x.find("Banana");
    if (i != x.end())
        std::cout << i->id;
    else 
        std::cout << "ERR";
}