我有类似的数据结构:
struct Data { std::string id; Blob data; };
现在我可以使用std::map
存储结构并按ID搜索,但我正在寻找一种方法来实现与std::set
相同的事情(因为我不需要分开ID和结构)。
std::set::find
当然将键类型作为参数,所以我可以做这样的事情(使用适当的构造函数):
set<Data> x; x.find(Data("some_id"));
但我想尽可能避免这种情况。它需要一个允许ID没有数据的构造函数,而且我真的不喜欢构造一个对象,只是将它用作搜索的关键。
所以我的问题是:有更好的方法吗?
答案 0 :(得分:1)
除非开销明显不可接受,否则我会选择std::map<std::string, Data *>
,或者可能std::map<std::string, boost::shared_ptr<Data> >
,假设您无权访问本机提供shared_ptr的编译器。
答案 1 :(得分:1)
投入一些构造函数和一个operator<
,事情变得非常简单。
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";
}
香蕉
我承认,这仍然会创建一个“虚拟”数据实例,但它似乎解决了这个问题。
答案 2 :(得分:1)
如果您不反对使用Boost,那么Boost.MultiIndex会使这非常简单,而不会增加任何不必要的低效率。这是一个有效创建set
Data
个Data::id
个对象的示例,这些对象以#include <string>
#include <ios>
#include <iostream>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/member.hpp>
namespace bmi = boost::multi_index;
typedef char const* Blob;
struct Data
{
std::string id;
Blob data;
void display() const { std::cout << "id: " << id << '\n'; }
};
typedef bmi::multi_index_container<
Data,
bmi::indexed_by<
bmi::ordered_unique<
bmi::member<Data, std::string, &Data::id>
>
>
> DataSet;
int main()
{
Data d1 = { "some_id", nullptr };
Data d2 = { "some_other_id", nullptr };
DataSet set;
set.insert(d1);
set.insert(d2);
set.find("some_id")->display();
// for exposition, find is actually returning an iterator
DataSet::const_iterator iter = set.find("some_other_id");
if (iter != set.end())
iter->display();
// set semantics -- newly_added is false here, because the
// container already contains a Data object with id "some_id"
Data d3 = { "some_id", "blob data" };
bool const newly_added = set.insert(d3).second;
std::cout << std::boolalpha << newly_added << '\n';
}
的值为基础:
{{1}}
答案 3 :(得分:0)
更好的方法是将id
索引设为data
。但是,由于您不想这样做,请尝试使用std::find_if( x.first(), x.end(), --predicate-- )
,其中谓词是函数对象或lambda函数谓词,用于将Data
与指定的id
进行比较。
答案 4 :(得分:0)
我意识到这个问题在此之前被问到了,但是:
从C ++ 14开始,可以在一个集合内进行搜索,而无需创建密钥类型的实例,其中std::set::find的额外重载采用模板化密钥。