2012-09-04 3 views
1

여기 내 질문입니다, 나는 두 배의 벡터를 가지고 있으며, 나는 그들 중 일부를 특정 조건 하에서 제거해야합니다. 다음 코드 예이다 : (1) 모든 요소들에 의해 제 사이즈 감소가 왼쪽으로 시프트 남았 소거 후 이후vector :: erase()가 위치를 변경합니까?

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--; 
     } 
     } 
    } 

, J를 감소 맞습니까?

좋아요. 작은 프로그램이고 성능에 대해서는별로 신경 쓰지 않아요.하지만 segmentation 오류가있어서 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; 
     } 
    } 
    } 

포인트 좌표 벡터 그래서 (X1, Y1, Z1, X2, Y2, Z3, ..., XN, YN, 아연)과 같이 : 여기서 코드이다. 아이디어가 있으십니까?

+2

삭제 된 모든 요소 *. 'std :: remove_if'는 많은 것들에 따라 더 효율적일 수 있습니다. –

답변

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(), 
     [&](double d) { return condition(appo[i], d); } 
    ), 
    appo.end() 
); 

당신은 : C++ 11에서

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

가 대신 ShouldRemove의 람다를 사용할 수 있습니다 C++ 03에서

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

과 유사한 ShouldRemove를 정의해야 std::bind1st 또는 boost::bind (C++ 03) 또는 std::bind (C++ 11)을 사용하는 몇 가지 옵션이 있지만 올바르게 이해하는 것은 매우 까다 롭습니다.