Вот мой вопрос, у меня есть вектор удвоения, и мне нужно устранить некоторые из них при определенных условиях. Вот пример кода:
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).
Любая идея?
Правильно уменьшить 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), но это довольно сложно понять правильно.
Других решений пока нет …