这是我的问题,我有一个双向量,我需要在一定条件下消除它们中的一些.这是一个代码示例:
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--;
}
}
}
Run Code Online (Sandbox Code Playgroud)
因为在擦除()之后我的大小减少了1并且所有元素左移左移,所以减少j是正确的吗?
好吧我决定不使用removeif,因为它是一个小程序,我现在不关心性能,但我得到了分段错误.这是代码:
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
point是一个坐标向量,如(x1,y1,z1,x2,y2,z3,...,xn,yn,zn).任何的想法?
递减是正确的j,因为在删除索引处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;
}
}
Run Code Online (Sandbox Code Playgroud)
完成后,您也可以使用迭代器i.
正如"eq-"在评论中所说,有一种标准算法可以帮助你.任你选,你是否更愿意在可用性方面的循环,但它通常是更有效,因为一边喊"擦除"洗牌沿着一步一个时间每一个元素,而remove_if跟踪"读取位置"和"写位置"所以它最多只复制一次每个元素.
appo.erase(
appo.remove_if(
appo.begin() + i + 1,
appo.end(),
ShouldRemove(appo[i])
),
appo.end()
);
Run Code Online (Sandbox Code Playgroud)
在C++ 03中,您必须定义ShouldRemove类似于:
struct ShouldRemove {
double lhs;
ShouldRemove(double d) : lhs(d) {}
bool operator()(double rhs) {
return condition(lhs, rhs);
}
};
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,您可以使用lambda而不是ShouldRemove:
appo.erase(
appo.remove_if(
appo.begin() + i + 1,
appo.end(),
[&](double d) { return condition(appo[i], d); }
),
appo.end()
);
Run Code Online (Sandbox Code Playgroud)
您还可以使用std::bind1st或boost::bind(在C++ 03中)或std::bind(在C++ 11中)使用某些选项,但要正确理解这些选项非常棘手.