这是我的问题,我有一个双向量,我需要在一定条件下消除它们中的一些。这是一个代码示例:
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--;
}
}
}
因为在擦除()之后我的大小减少了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;
}
}
}
point是一个坐标向量,如(x1,y1,z1,x2,y2,z3,...,xn,yn,zn)。 有什么想法吗?
答案 0 :(得分:6)
递减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;
}
}
完成后,您也可以使用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::bind1st
或boost::bind
(在C ++ 03中)或std::bind
(在C ++ 11中)使用一些选项,但要正确理解这些选项非常棘手。