문제
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);
또한보십시오 표준::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)에서 작동합니다.