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

Поскольку после стирания () мой размер уменьшился на 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;
}
}
}

точка — это вектор координат, поэтому что-то вроде (x1, y1, z1, x2, y2, z3, …, xn, yn, zn).
Любая идея?

1

Решение

Правильно уменьшить 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 вы можете использовать лямбду вместо mustRemove:

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), но это довольно сложно понять правильно.

6

Другие решения

Других решений пока нет …