如何擦除double for循环中的矢量元素

How to erase a vector element within double for loop

本文关键字:循环 元素 for double 何擦除 擦除      更新时间:2023-10-16

我有一个结构的向量

vector<contour> hotspots;

轮廓是我在下面定义的结构

struct contour
{
    double arc;
    double area;
    Point2f center;
    double me;
    double hullArea;
    vector<Point> contourVector;
    vector<Point> hullVector;
    bool operator <(const contour& comp)
    {
        return me < comp.me;
    }
};

所以我想做的是循环遍历,并删除另一个轮廓中包含的每个轮廓,我可以让它在很大程度上工作,但有时我会出现索引错误,我认为这与当我删除一个元素时索引会出错有关,所以我超出了范围。这是我写的循环:

vector<vector<Point>> cleanUp(vector<Point2f> centers, vector<Moments> areas, vector<vector<Point>> contours)
{
    for (int i = 0; i < contours.size(); i++)
        for (int j = 0; j < contours.size(); j++)
            if (i != j)
            {
                if ((areas[i].m00 < areas[j].m00) == true && (pointPolygonTest(contours[j], centers[i], false) > 0) == true)
                {
                    contours.erase(contours.begin() + i);
                    centers.erase(centers.begin() + i);
                    areas.erase(areas.begin() + i);
                }
            }
    return contours;
}

我尝试了一些不同的解决方案,比如I-1,但它删除了错误的轮廓,而不是使用擦除,而是用最后一个覆盖我想删除的元素,然后使用.pop_back删除最后一个元素,但这似乎也不起作用。有什么想法吗?

编辑:修复了区域和中心不同步的问题,但现在只要我调用函数来擦除一些轮廓,问题就会立即出现。

您可以为要删除的项保留一个索引列表,并在最后删除这些索引处的项。

vector<vector<Point>> cleanUp(vector<Point2f> centers,
                              vector<Moments> areas,
                              vector<vector<Point>> contours)
{
   std::<int> itemsToErase;
    for (int i = 0; i < contours.size(); i++)
        for (int j = 0; j < contours.size(); j++)
            if (i != j)
            {
                if ((areas[i].m00 < areas[j].m00) == true &&
                    (pointPolygonTest(contours[j], centers[i], false) > 0) == true)
                {
                   itemsToErase.push_front(i);
                }
            }
    while  ( !itemsToErase.empty() )
    {
       int i = itemsToErase.back();
       contours.erase(contours.begin() + i);
       centers.erase(centers.begin() + i);
       areas.erase(areas.begin() + i);
       itemsToErase.pop_back();
    }
    return contours;
}

使用迭代器,我会尝试这种方法:

#include <iterator>
template <typename BinaryPred>
void RemoveIfPairwise(std::vector<T> & v, BinaryPred f)
{
    for (auto it1 = v.begin(); it1 != v.end(); ++it1)
    {
        for (auto it2 = std::next(it1); it2 != v.end(); )
        {
            if (f(*it1, *it2)) { it2 = v.erase(it2); }
            else               { ++it2;              }
        }
    }
}

这使用了std::vector的迭代器非无效保证,例如擦除不会在擦除点之前使迭代器无效(因此it1不需要特殊处理)。

注意,这个循环只检查不同元素对;您需要修改它来检查对角线。