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

时间:2012-03-23 03:49:22

标签: c++ search stl

我有一个std :: vector,元素作为对,需要在某些范围内找到第一个组件的所有元素,例如,找到所有元素,使得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.first-ref.first)&lt; 0.01的元素将被返回。这是我在代码中遗漏的东西吗?感谢。

3 个答案:

答案 0 :(得分:2)

equal_range需要排序范围。

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

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

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

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

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

要实际找到.6返回true的所有元素,您可以使用std::bind(comp({.5,.5}, _1))(尽管有多种不同的方法可以执行此操作,具体取决于您的具体需求)。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

您的比较函数不满足严格弱排序的要求,即对于两个元素,例如a和b,如果comp(a, b) == truecomp(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