2

Here is my question, I have a vector of double and I need eliminate some of them under a certain condition. Here is a code example:

 vector <double> appo;
 for(int i=0;i<appo.size();i++){
       for(int j=i+1;j<appo.size();j++){
         if( condition(appo[i],appo[j]) ){
           appo.erase(appo.begin()+j);
           j--;
         }
       }
    }

Since after the erase() my size decrease by 1 and all the elements got left shifted by left, is correct to decrease j?

Ok I decide to don't use the removeif because it's a small program and I don't care right now about performance, but I got segmentation fault. Here is the code:

vector <double> *point;
for(int i=0;i<point->size();i+=3){
     for(int j=i+3;j<point->size();j+=3){
       if(distance((*point)[i],(*point)[i+1],(*point)[i+2],(*point)[j],(*point)[j+1],(*point)[j+2]) < treshold){
         point->erase(point->begin()+j,point->begin()+j*3);
         j-=3;
       }
     }
  }

point is a vector of coordinates so something like (x1,y1,z1,x2,y2,z3,...,xn,yn,zn). Any idea?

4

1 回答 1

6

递减是正确的j,因为在擦除 index 处j的元素后,之前所在的元素j+1现在位于j,所以你想用相同的值再次重复循环j。减少它会产生这种效果,因为循环本身会增加它。

您还可以考虑使用迭代器而不是索引:

vector<double>::iterator j = appo.begin() + i + 1;
while (j != appo.end()) {
    if (condition(appo[i], *j)) {
        j = appo.erase(j);
    } else {
        ++j;
    }
}

完成后,您也可以使用迭代器i

正如“eq-”在评论中所说,有一个标准算法可以帮助你。就可用性而言,您是否更喜欢循环,但它通常更有效,因为重复调用“擦除”一次将每个元素洗牌,同时remove_if跟踪“读取位置”和“写入位置” ",所以它最多只复制每个元素一次。

appo.erase(
    appo.remove_if(
        appo.begin() + i + 1,
        appo.end(),
        ShouldRemove(appo[i])
    ),
    appo.end()
);

在 C++03 中,您必须定义ShouldRemove类似于:

struct ShouldRemove {
    double lhs;
    ShouldRemove(double d) : lhs(d) {}
    bool operator()(double rhs) {
        return condition(lhs, rhs);
    }
};

在 C++11 中,您可以使用 lambda 代替 ShouldRemove:

appo.erase(
    appo.remove_if(
        appo.begin() + i + 1,
        appo.end(),
        [&](double d) { return condition(appo[i], d); }
    ),
    appo.end()
);

您还可以使用std::bind1stboost::bind(在 C++03 中)或std::bind(在 C++11 中)使用一些选项,但这些选项很难正确理解。

于 2012-09-04T19:24:23.903 回答