假设我们有一个map
,包含更大的对象和索引值。索引值也是较大对象的一部分。
我想知道的是,是否可以用map
替换set
,提取索引值。
通过提取索引值,可以很容易地创建一个set
,在仿函数上对两个较大的对象进行排序。
通过索引值进行搜索,我认为默认情况下set
不支持。
我在考虑使用std::find_if
,但我认为线性搜索,忽略了我们设定的事实。
然后我考虑使用std::binary_search
与仿函数比较较大的对象和值,但我相信它在这种情况下不起作用,因为它不会使用该结构并会使用遍历因为它没有随机访问迭代器。它是否正确?或者是否存在在set
上正确处理此调用的重载?
然后我最后考虑使用boost::containter::flat_set
,因为它有一个底层向量,因此可能应该能够与std::binary_search
一起使用?
但也许有更简单的方法可以做到这一点?
在你回答之前只使用一张应该使用地图的地图 - 我实际上正在使用一个手动排序的矢量(好std::lower_bound
)并且正在考虑用boost::containter::flat_set
替换它,但是这样做似乎不太可能,所以我可能会坚持使用矢量。
答案 0 :(得分:3)
C ++ 14将引入通过不需要构造整个存储对象的键进行查找的能力。这可以使用如下:
#include <set>
#include <iostream>
struct StringRef {
StringRef(const std::string& s):x(&s[0]) { }
StringRef(const char *s):x(s) { std::cout << "works: " << s << std::endl; }
const char *x;
};
struct Object {
long long data;
std::size_t index;
};
struct ObjectIndexer {
ObjectIndexer(Object const& o) : index(o.index) {}
ObjectIndexer(std::size_t index) : index(index) {}
std::size_t index;
};
struct ObjComp {
bool operator()(ObjectIndexer a, ObjectIndexer b) const {
return a.index < b.index;
}
typedef void is_transparent; //Allows the comparison with non-Object types.
};
int main() {
std::set<Object, ObjComp> stuff;
stuff.insert(Object{135, 1});
std::cout << stuff.find(ObjectIndexer(1))->data << "\n";
}
更一般地说,使用Boost.MultiIndex可以解决有多种索引数据方式的问题。
答案 1 :(得分:1)
使用boost::intrusive::set
可以直接利用对象的索引值。它具有对数复杂度的find(const KeyType & key, KeyValueCompare comp)
函数。还有其他基于展开树,AVL树,替罪羊树等的集合类型,根据您的要求可能会有更好的表现。
答案 2 :(得分:0)
如果将以下内容添加到包含的对象类型中:
然后你可以将你的索引类型传递给find,lower_bound,equal_range等......它会按你想要的方式运行。当你将索引传递给set(或flat_set)的find方法时,它将构造一个包含类型的虚拟对象,用于比较。
现在,如果您的对象非常大,或构建成本高,那么这可能不是您想要的方式。