IT

특정 값을 가진 stl 벡터에서 항목을 어떻게 제거합니까?

lottoking 2020. 6. 29. 07:39
반응형

특정 값을 가진 stl 벡터에서 항목을 어떻게 제거합니까?


stl 벡터에 대한 API 설명서를보고 있었고 벡터 클래스에 특정 값을 가진 요소를 제거 할 수있는 메소드가 없다는 것을 알았습니다. 이것은 일반적인 작업처럼 보이지만이 작업을 수행 할 방법이없는 것이 이상합니다.


std::remove실제로 컨테이너에서 요소를 지우지는 않지만 컨테이너의 끝에 container_type::erase있는 추가 요소를 실제로 제거 하기 위해 전달 될 수있는 새로운 끝 반복자를 반환합니다 .

std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());

제거 할 경우 항목을, 다음은 좀 더 효율적입니다.

std::vector<int> v;


auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
    v.erase(it);

또는 주문이 중요하지 않은 경우 항목을 이동하는 오버 헤드를 피할 수 있습니다.

std::vector<int> v;

auto it = std::find(v.begin(), v.end(), 5);

if (it != v.end()) {
  using std::swap;

  // swap the one to be removed with the last element
  // and remove the item at the end of the container
  // to prevent moving all items after '5' by one
  swap(*it, v.back());
  v.pop_back();
}

전역 메소드 std :: remove를 begin 및 end 반복자와 함께 사용하고 std :: vector.erase를 사용하여 실제로 요소를 제거하십시오.

문서 링크
std :: remove http://www.cppreference.com/cppalgorithm/remove.html
std :: vector.erase http://www.cppreference.com/cppvector/erase.html

std::vector<int> v;
v.push_back(1);
v.push_back(2);

//Vector should contain the elements 1, 2

//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);

//Erase the "removed" elements.
v.erase(newEnd, v.end());

//Vector should now only contain 2

내 오류를 지적한 Jim Buck에게 감사합니다.


다른 답변은이 작업을 수행하는 방법을 다루고 있지만, 이것이 벡터 API에없는 것이 실제로 이상하지 않다는 것을 지적했습니다. 벡터에 대한 벡터를 통한 비효율적 인 선형 검색과 무리 그것을 제거하기 위해 복사.

이 작업을 집중적으로 수행하는 경우 이러한 이유로 std :: set을 고려해 볼 가치가 있습니다.


정렬되지 않은 벡터가있는 경우 마지막 벡터 요소와 간단히 교체 할 수 있습니다 resize().

정렬 된 용기로, 당신은 최상의 떨어져 있습니다 std::vector::erase(). std::remove()정의되어 <algorithm>있지만 실제로는 지우지 않습니다. (문서를주의해서 읽으십시오).


더 짧은 해결책 (벡터 이름을 4 번 반복하지 않는)은 Boost를 사용하는 것입니다.

#include <boost/range/algorithm_ext/erase.hpp>

// ...

boost::remove_erase(vec, int_to_remove);

http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html을 참조 하십시오


술어를 사용할 수 있으려면 std :: remove_if 도 참조하십시오 ...

위 링크의 예는 다음과 같습니다.

vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 4 2 8 5 7"

vector<int>::iterator new_end = 
    remove_if(V.begin(), V.end(), 
              compose1(bind2nd(equal_to<int>(), 0),
                       bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]

copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
    // The output is "1 5 7".

에서 C ++ 20 :

비 멤버 함수가 도입 std::erase되어 벡터와 값을 입력으로 제거합니다.

ex:

std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);

If you want to do it without any extra includes:

vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
    IComponent* juggler;

    if (componentToRemove != NULL)
    {
        for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
        {
            if (componentToRemove == myComponents[currComponentIndex])
            {
                //Since we don't care about order, swap with the last element, then delete it.
                juggler = myComponents[currComponentIndex];
                myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
                myComponents[myComponents.size() - 1] = juggler;

                //Remove it from memory and let the vector know too.
                myComponents.pop_back();
                delete juggler;
            }
        }
    }
}

Two ways are there by which you can use to erase an item particularly. lets take a vector

std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);

1) Non efficient way : Although it seems to be quite efficient but it's not because erase function delets the elements and shifts all the elements towards left by 1. so its complexity will be O(n^2)

std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
   if(*itr == value)
   { 
      v.erase(itr);
   }
   else
       ++itr;
}

2) Efficient way ( RECOMMENDED ) : It is also known as ERASE - REMOVE idioms .

  • std::remove transforms the given range into a range with all the elements that compare not equal to given element shifted to the start of the container.
  • So, actually don't remove the matched elements. It just shifted the non matched to starting and gives an iterator to new valid end. It just requires O(n) complexity.

output of the remove algorithm is :

10 20 30 50 40 50 

as return type of remove is iterator to the new end of that range.

template <class ForwardIterator, class T>
  ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);

Now use vector’s erase function to delete elements from the new end to old end of the vector. It requires O(1) time.

v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );

so this method work in O(n)

참고URL : https://stackoverflow.com/questions/39912/how-do-i-remove-an-item-from-a-stl-vector-with-a-certain-value

반응형