IT story

벡터에서 요소 지우기

hot-time 2020. 8. 31. 08:27
반응형

벡터에서 요소 지우기


지우기 방법을 사용하여 벡터에서 요소를 지우고 싶습니다. 그러나 여기서 문제는 요소가 벡터에서 한 번만 발생한다는 보장이 없다는 것입니다. 여러 번 나타날 수 있으며 모두 지워야합니다. 내 코드는 다음과 같습니다.

void erase(std::vector<int>& myNumbers_in, int number_in)
{
    std::vector<int>::iterator iter = myNumbers_in.begin();
    std::vector<int>::iterator endIter = myNumbers_in.end();
    for(; iter != endIter; ++iter)
    {
        if(*iter == number_in)
        {
            myNumbers_in.erase(iter);
        }
    }
}

int main(int argc, char* argv[])
{
    std::vector<int> myNmbers;
    for(int i = 0; i < 2; ++i)
    {
        myNmbers.push_back(i);
        myNmbers.push_back(i);
    }

    erase(myNmbers, 1);

    return 0;
}

이 코드는 벡터를 반복하는 동안 벡터의 끝을 변경하기 때문에 분명히 충돌합니다. 이를 달성하는 가장 좋은 방법은 무엇입니까? 즉, 벡터를 여러 번 반복하거나 벡터의 복사본을 하나 더 만들지 않고도이를 수행 할 수있는 방법이 있습니까?


사용 제거를 / 삭제 관용구 :

std::vector<int>& vec = myNumbers; // use shorter name
vec.erase(std::remove(vec.begin(), vec.end(), number_in), vec.end());

의 시작 부분에서 remove제거 할 값 ( number_in) 과 다른 요소 압축하고 vector해당 범위 이후의 첫 번째 요소로 반복자를 반환합니다. 그런 다음 erase이러한 요소 (값이 지정되지 않음)를 제거합니다.


erase를 호출하면 반복기가 무효화되며 다음을 사용할 수 있습니다.

void erase(std::vector<int>& myNumbers_in, int number_in)
{
    std::vector<int>::iterator iter = myNumbers_in.begin();
    while (iter != myNumbers_in.end())
    {
        if (*iter == number_in)
        {
            iter = myNumbers_in.erase(iter);
        }
        else
        {
           ++iter;
        }
    }

}

또는 std :: remove_if를 functor 및 std :: vector :: erase와 함께 사용할 수 있습니다 .

struct Eraser
{
    Eraser(int number_in) : number_in(number_in) {}
    int number_in;
    bool operator()(int i) const
    {
        return i == number_in;
    }
};

std::vector<int> myNumbers;
myNumbers.erase(std::remove_if(myNumbers.begin(), myNumbers.end(), Eraser(number_in)), myNumbers.end());

이 경우 자체 functor를 작성하는 대신 std :: remove 사용할 수 있습니다 .

std::vector<int> myNumbers;
myNumbers.erase(std::remove(myNumbers.begin(), myNumbers.end(), number_in), myNumbers.end());

  1. 인덱스 액세스를 사용하여 반복 할 수 있습니다.

  2. O (n ^ 2) 복잡성을 피하기 위해 두 개의 인덱스, i-현재 테스트 인덱스, j-인덱스를 사용하여 다음 항목을 저장하고주기가 끝날 때 벡터의 새 크기를 사용할 수 있습니다.

암호:

void erase(std::vector<int>& v, int num)
{
  size_t j = 0;
  for (size_t i = 0; i < v.size(); ++i) {
    if (v[i] != num) v[j++] = v[i];
  }
  // trim vector to new size
  v.resize(j);
}

In such case you have no invalidating of iterators, complexity is O(n), and code is very concise and you don't need to write some helper classes, although in some case using helper classes can benefit in more flexible code.

This code does not use erase method, but solves your task.

Using pure stl you can do this in the following way (this is similar to the Motti's answer):

#include <algorithm>

void erase(std::vector<int>& v, int num) {
    vector<int>::iterator it = remove(v.begin(), v.end(), num);
    v.erase(it, v.end());
}

Depending on why you are doing this, using a std::set might be a better idea than std::vector.

It allows each element to occur only once. If you add it multiple times, there will only be one instance to erase anyway. This will make the erase operation trivial. The erase operation will also have lower time complexity than on the vector, however, adding elements is slower on the set so it might not be much of an advantage.

This of course won't work if you are interested in how many times an element has been added to your vector or the order the elements were added.

참고URL : https://stackoverflow.com/questions/347441/erasing-elements-from-a-vector

반응형