Как использовать стирание и итератор для удаления элемента в двумерном векторе? - PullRequest
2 голосов
/ 29 октября 2019

Двумерный вектор: (Я хочу пройти через вектор, и если я найду то же имя, что и «и», то удаляю или стираю его, но почему он может работать только с ним1, а не с ним2? Как это исправить? )

vector<Animals>numberOfAnimals(12);
vector<vector<Animals>>all(4,numberOfAnimals);

void delete_item(vector<vector<Animals>>&all,string ans)
{
    for (auto it1=all.begin();it1!=all.end();it1++)
    {
        for (auto it2=(*it1).begin();it2!=(*it1).end();it2++)
        {
            if ((*it2).getter_name()==ans)
            {
                all.erase(it1);  //no error
                all.erase(it2--); //error
            }
        }
    }
}

1 Ответ

1 голос
/ 29 октября 2019

all - вектор векторов. it1 - это итератор для all, поэтому его можно передать в all.erase. it1 относится к одному из векторов внутри all.

it2 не является итератором для all, поэтому его нельзя передать в all.erase. it2 является итератором для вектора *it1, который является вектором Animals. it2 можно передать на it1->erase. it2 относится к одному из Animals в *it1.


Однако обратите внимание, что удаление итератора для вектора делает его недействительным. it1 и it2 по-прежнему используются в цикле так, что это нельзя делать на недопустимом итераторе. Таким образом, использование erase в цикле без исправления итератора ведет к неопределенному поведению.

Идиоматическим способом выборочного удаления некоторых элементов контейнера является удаление-удаление:

auto predicate = [&ans](const Animals& a) {
    return a.getter_name()==ans;
};
for(std::vector<Animals>& v : all) {
    v.erase(std::remove_if(v.begin(), v.end(), predicate));
}

Это удаляет всеAnimals, которые соответствуют предикату в каждом из векторов в all.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...