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

StackOverflow https://stackoverflow.com/questions/39912

  •  09-06-2019
  •  | 
  •  

문제

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를 시작 및 끝 반복자와 함께 사용한 다음 std::Vector.erase를 사용하여 실제로 요소를 제거합니다.

문서 링크
표준::제거 http://www.cppreference.com/cppalgorithm/remove.html
표준::벡터.지우기 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

또한보십시오 표준::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, 제거할 벡터와 값을 입력으로 사용합니다.

전:

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

추가 항목 없이 수행하려면 다음을 포함합니다.

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;
            }
        }
    }
}

특히 항목을 지우는 데 사용할 수 있는 두 가지 방법이 있습니다.벡터를 사용하자

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) 비효율적인 방법 : 매우 효율적인 것처럼 보이지만 삭제 기능이 요소를 삭제하고 모든 요소를 ​​왼쪽으로 1만큼 이동하기 때문에 그렇지 않습니다.따라서 복잡도는 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) 효율적인 방법 (권장) :그것은 또한로 알려져 있습니다 지우기 - 숙어 제거 .

  • std::remove는 주어진 범위를 주어진 요소와 같지 않은 모든 요소가 컨테이너의 시작 부분으로 이동된 범위로 변환합니다.
  • 따라서 실제로 일치하는 요소를 제거하지 마십시오.일치하지 않는 부분을 시작 부분으로 이동하고 새로운 유효한 끝 부분에 반복자를 제공합니다.O(n) 복잡성만 필요합니다.

제거 알고리즘의 출력은 다음과 같습니다.

10 20 30 50 40 50 

제거의 반환 유형은 해당 범위의 새로운 끝 부분에 대한 반복자입니다.

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

이제 벡터의 지우기 기능을 사용하여 벡터의 새 끝에서 이전 끝까지 요소를 삭제합니다.O(1) 시간이 필요합니다.

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

따라서 이 방법은 O(n)에서 작동합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top