从矢量
std::vector<S> structures;
包含
类型的结构struct S {
double x;
double y;
double weight;
};
我想反复获取具有特定权重的所有结构,即我想执行以下伪代码:
do 1000 times:
weight = GetASpecificWeight()
MatchingStructures = structures.GetAllStructuresWithWeight(weight)
为了有效地做到这一点,我想对structures
向量进行排序,并在每次迭代中进行二进制搜索。
如何使用std :: code实现此功能?
答案 0 :(得分:1)
可以使用std::sort
对矢量进行排序,并且可以使用std::equal_range
查找具有指定权重的元素范围。
但是,正如Daniel在评论中指出的那样,getASpecificWeight()
很可能会返回一个双精度而不是Structure
,所以为了调用equal_range
,我们需要创建一个dummy Structure
或将double
与Structures
与所需语义进行比较的函数对象。单个lambda不起作用,因为二进制搜索需要能够将Structure
s与两种权重进行比较。
首先,让我们创建一个虚拟Structure
,因为这是更少的代码。
总的来说,它可能看起来像这样
auto sort_structure_by_weight_asc = [](Structure const& s1, Structure const& s2) {
return s1.weight < s2.weight;
};
std::sort(structures.begin(), structures.end(),
sort_structure_by_weight_asc);
for (auto i = 0; i < 1000; ++i) {
auto weight = GetASpecificWeight();
auto const dummy_structure = Strucutre{0.0, 0.0, weight};
auto range = std::equal_range(structures.cbegin(), structures.cend(),
dummy_structure, sort_structure_by_weight_asc);
if (range.first != structures.cend() && range.second != structures.cbegin()) {
// do whatever you want here
// if the `if`-condition isn't satisfied, no structure
// had weight `weight`.
}
}
如果您需要修改structures
向量中的元素,可以在调用cbegin
和cend
时替换std::equal_range
和if
- 条件分别为begin
/ end
。
但是,我个人认为创建虚拟结构非常干净,所以让我们看看自定义函数对象如何改进代码。
函数对象本身可以定义为
struct ComparatorStructureToWeightAsc {
bool operator()(Structure const& s, double weight) const {
return s.weight < weight;
}
bool operator()(double weight, Structure const& s) const {
return weight < s.weight;
}
};
然后代码看起来像这样:
std::sort(structures.begin(), structures.end(),
[](auto const& s1, auto const& s2) { return s1.weight < s2.weight; });
for (auto i = 0; i < 1000; ++i) {
auto weight = GetASpecificWeight();
auto range = std::equal_range(structures.cbegin(), structures.cend(),
weight, ComparatorStructureToWeightAsc);
if (range.first != structures.cend() && range.second != structures.cbegin()) {
// do whatever you want here
// if the `if`-condition isn't satisfied, no structure
// had weight `weight`.
}
}
正如你所看到的那样,我不善于命名,所以必须命名用于将Structures与权重进行比较的函数对象有点尴尬,特别是如果它只在这个地方使用的话。如果您可以访问Boost,特别是Boost.Functional/OverloadedFunction,则可以使用两个lambda而不是手工制作的函数对象。
然后代码如下:
std::sort(structures.begin(), structures.end(),
[](auto const& s1, auto const& s2) { return s1.weight < s2.weight; });
for (auto i = 0; i < 1000; ++i) {
auto weight = GetASpecificWeight();
auto range = std::equal_range(structures.cbegin(), structures.cend(), weight,
boost::make_overloaded_function(
[](Structure const& s, double weight) { return s.weight < weight; },
[](double weight, Structure const& s) { return weight < s.weight; }));
if (range.first != structures.cend() && range.second != structures.cbegin()) {
// do whatever you want here
// if the `if`-condition isn't satisfied, no structure
// had weight `weight`.
}
}