C ++ вложенный в цикл с удаляемыми элементами - PullRequest
0 голосов
/ 04 января 2019

Я хотел бы проверить все элементы вектора друг против друга. Проверяя условие, элемент должен быть удален.

Один из подходов заключался в удалении элементов с помощью вложенных циклов

for (int a = 0; a < rs.size(); a++)
{
    Point A = rs[a];

    for (int b = 1; b <= rs.size(); b++)
    {
        Point B = rs2[b];
        float distance = sqrt(pow(B.x - A.x, 2) + pow(B.y - A.y, 2) * 1.0);

        if (distance < 10.0)
        {
            if (distance > 0)
            {
                rs.erase(rs.begin() + b);
            }
        }
    }
}

но это повлияет на вектор и его размер во время выполнения.

Второй подход состоял в том, чтобы собрать индекс b в unordered_set, но как я могу удалить элементы с соответствующим индексом в исходном векторе?

unordered_set<int> index;

for (int a = 0; a < rs.size(); a++)
{
    Point A = rs[a];

    for (int b = 0; b < rs.size(); b++)
    {
        Point B = rs2[b];
        float distance = sqrt(pow(B.x - A.x, 2) + pow(B.y - A.y, 2) * 1.0);

        if (distance < 10.0)
        {
            if (distance > 0)
            {
                index.insert(b);
            }
        }
    }
}

Как и следовало ожидать, этот подход также не работает:

for (const int& idx : index)
{
    rs.erase(rs.begin() + idx);
}

Любая помощь?

Ответы [ 3 ]

0 голосов
/ 04 января 2019

Чтобы быть как можно более надежным, я бы использовал std :: for_each. В функции, выполняемой для каждого объекта, примерно:

  • Выполнить расчет необходимо
  • проверьте ваше состояние: сохранить элемент или нет
  • если вы хотите сохранить его, добавьте его в новый вектор out, иначе не делайте

Затем очистите исходный вектор, когда вы закончите, и поменяйте местами вектор входа и выхода. Переместите объекты в (умные!) - указатели для повышения эффективности (меньше копирования).

For_each в сочетании с созданием нового вектора должен сделать это очень устойчивым к потенциальным изменениям размера и перераспределениям, которые могут произойти при использовании std :: vector.

0 голосов
/ 04 января 2019

Извините, ребята, я изменил проверку расстояния до точки вставки ...

vector<Point> rois;
for (int y = 0; y < result.rows; y++)
{
    for (int x = 0; x < result.cols; x++)
    {
        float qt = result.at<float>(y, x);

        if (qt >= threshVal)
        {
            Point A = Point(x, y);

            bool isNear = true;

            if (rois.size() > 0)
            {
                for (Point &P : rois)
                {
                    float distance = sqrt(pow(P.x - A.x, 2) + pow(P.y - A.y, 2) * 1.0);

                    if (distance < 10.0)
                    {
                        isNear = false;
                        break;
                    }
                }
                if (isNear)
                {
                    rois.push_back(A);
                }
            }
            else
            {
                rois.push_back(A);
            }
        }
    }
}

Это намного проще, чем предыдущий подход.

Но спасибо за ответы.

0 голосов
/ 04 января 2019

Вы можете удалить индексы из вектора с обратной петлей в последнем предложенном вами предложении. Просто сделайте это index вектором. Давайте назовем это toRemove.

for (int i = toRemove.size() - 1; i >= 0; i--)
{
    rs.erase(rs.begin() + toRemove[i]);
}

Только будьте осторожны, чтобы этот цикл имел подписанный индекс. В противном случае вы можете потерять. Вы можете сделать это «лучше» с помощью обратного итератора. Это всего лишь подтверждение концепции.

...