使用std::equalrange来搜索某些范围内的向量

using std::equal_range to search the vector within some ranges

本文关键字:范围内 向量 搜索 std equalrange 使用      更新时间:2023-10-16

我有一个std::向量,元素是对的,需要在一些范围内找到第一个分量的所有元素,例如,找到所有元素,使得abs(第一个分量值-引用)<0.01,我从的其他帖子中得到了代码

bool comp(pair<double, double> v1, pair<double, double> v2)
{
  return (abs(v1.first-v2.first)<0.001);
}
vector< pair<double, double> data;
for (int i=0; i<10; i++)
{
  double a, b; 
  // a & b are initialized randomly (the code was not shown here)
  data.push_back(make_pair(a, b));
}
// we sort the vector here based on the pair.first (code not shown)
// compval is used as reference value, i.e. we are going to find all elements with     abs(pair.first-ref.first)<0.01
pair<double, double> ref
ref.first = 0.5;
ref.second = 0.5;
std::pair< vector< pair<double, double>::iterator, vector< pair<double, double>::iterator> const range = std::equal_range(data.begin(), data.end(), ref, comp);

但是如果你观察由结果范围给出的所有元素,你会发现数据的所有元素而不是满足abs(pair.firstref.first)<将返回0.01。代码中有我遗漏的内容吗?谢谢

equal_range需要一个排序的范围。

比较函数所隐含的顺序与将范围排序的顺序不匹配,因此对equal_range的调用具有未定义的行为。

例如,假设您的列表包含{{.5, 0}, {.6, 0}}(这些都经过排序),然后将std::bind(comp({.5,.5},_1))应用于每个元素。

CCD_ 5将返回true。

comp({.5,.5},{.6,0})将返回false。

您的排序顺序是:".5小于.6",但同时您的comp函数是说".6小于.5"(因为有一个值小于.5但不小于.6)。这是矛盾的,也是你问题的原因。

要真正找到使std::bind(comp({.5,.5}, _1))返回true的所有元素,可以使用std::copy_if(data.begin(), data.end(), some_output_iterator, std::bind(comp(ref, std::placeholders::_1)))(尽管根据您的确切需求,有多种不同的方法)。

您的比较函数不满足严格弱排序的要求,即对于a和b这两个元素,如果comp(a, b) == true,则comp(b, a)应为false

你可能想要更像这样的东西:

struct Comp {
  double target;
  bool operator()(const pair<double, double>& lhs,
                  const pair<double, double>& rhs) const {
    return abs(lhs.first - target) < abs(rhs.first - target);
  }
};
vector< pair<double, double> > data;
data.push_back(make_pair(0.1, 1.0));
data.push_back(make_pair(0.15, 1.2));
data.push_back(make_pair(0.189, 2.1));
data.push_back(make_pair(0.19, -2.1));
data.push_back(make_pair(0.192, 3.1));
data.push_back(make_pair(0.2, 0.1));
data.push_back(make_pair(0.205, 0.1));
data.push_back(make_pair(0.205, 0.0));
data.push_back(make_pair(0.206, 12.1));
data.push_back(make_pair(0.21, -12.9));
data.push_back(make_pair(0.3, 3.4));
data.push_back(make_pair(0.5, 7.5));
// We *must* sort the vector using the same comparison function that we're
// about to use to get the lower and upper bounds
Comp comp;
comp.target = 0.2;
sort(data.begin(), data.end(), comp);
// Get the lower bound
pair<double, double> low(make_pair(comp.target, 0.0));
vector< pair<double, double> >::iterator lower =
    lower_bound(data.begin(), data.end(), low, comp);
// Get the upper bound
pair<double, double> up(make_pair(comp.target + 0.01, 0.0));
// N.B. use "lower_bound" here to get upper bound of target + 0.01 exclusive.
//      If we want to include target + 0.01, use "upper_bound"
vector< pair<double, double> >::iterator upper =
    lower_bound(data.begin(), data.end(), up, comp);
for_each(lower, upper, [](const pair<double, double> &data_point) {
  cout << data_point.first << "t" << data_point.second << "n";
});


输出:

0.2     0.1
0.205   0.1
0.205   0
0.206   12.1
0.192   3.1
0.21    -12.9

我认为应该在函数comp()中使用fabs而不是abs