stl 벡터에 대한 API 설명서를보고 있었고 벡터 클래스에 특정 값을 가진 요소를 제거 할 수있는 메소드가 없다는 것을 알았습니다. 이것은 일반적인 작업처럼 보이지만이 작업을 수행 할 방법이없는 것이 이상합니다.
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());
vec.end()
또는 호출의 양쪽에서 동일해야합니다 std::remove
. 안전한 것처럼 웹의 다른 부분을 읽을 때 나에게 보이지만 명확하게 명시해야합니다.
vec.end()
같을 필요는 없습니다. 그것은 정확해야합니다 (그렇습니다).
vec.end()
동일해야하지만 std::remove
변경하지 않기 때문에 괜찮 습니다. 매개 변수의 평가 순서가 지정되지 않았으므로 두 번째 값 vec.end()
이 사용되는 시간까지 여전히 유효한지 알 수 없습니다 . 그것이 같은 이유는 간단 std::remove
합니다. 컨테이너의 크기를 변경하지 않고 단지 내용을 이동시킵니다.
std::remove
단 하나의 주장 만 취합니다 . 즉 const char *_Filename
. 어떤 방법으로 전화해야합니까?
remove
파일을 삭제하는 버전입니다 . 컨테이너를 다루는 <algorithm>
해당 버전에 액세스하려면 포함해야합니다 remove
.
제거 할 경우 항목을, 다음은 좀 더 효율적입니다.
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에게 감사합니다.
더 짧은 해결책 (벡터 이름을 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을 참조 하십시오
에서 C ++ 20 :
멤버가 아닌 함수가 도입 std::erase
되어 벡터와 값을 입력으로 제거합니다.
전의:
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
map::erase
! 와 같은 컨테이너 특정 속성을 활용합니다 .
술어를 사용할 수 있으려면 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".
추가 포함없이 수행하려면 다음을 수행하십시오.
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) 효율적인 방법 (권장) : 삭제 제거 관용구 라고도 합니다.
제거 알고리즘의 출력은 다음과 같습니다.
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)에서 작동합니다
*
C ++ 커뮤니티가 귀하의 요청을 들었습니다 :)
*
C ++ 20 은 지금 쉬운 방법을 제공합니다. 다음과 같이 간단합니다.
#include <vector>
...
vector<int> cnt{5, 0, 2, 8, 0, 7};
std::erase(cnt, 0);
std :: erase 및 std :: erase_if를 확인해야합니다 .
값의 모든 요소 (여기서는 '0')를 제거 할뿐만 아니라 O (n) 시간 복잡성으로 수행합니다. 당신이 얻을 수있는 가장 좋은 것입니다.
컴파일러가 C ++ 20을 지원하지 않으면 erase-remove 이디엄 을 사용해야합니다 .
#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end());