2013-08-03 2 views
4

순서를 유지하면서 문자열 요소가 포함 된 벡터 컨테이너에서 중복 요소를 삭제하는 방법이 있습니까?순서를 유지하면서 std :: vector에서 중복 요소를 지우거나 지우는 방법은 무엇입니까?

지금까지 set 메소드를 사용했지만 주문을 유지하지 않습니다.

이 문제와 관련하여 remove_if를 사용하는 방법을 모르겠습니다.

+1

컨테이너에 순서가있는 경우 (즉, 요소가 정렬 된 경우) 중복 된 연속입니다. 그래서 문제는 어디에 있습니까? 중복을 제거하면 주문이 수정되지 않습니다. – Manu343726

+5

@ Manu343726 : "주문 있음"은 "정렬 됨"을 의미하지 않습니다. –

+0

Unix 명령 'uniq'과 같은 연속 된 반복 값이나 이후의 reprtitions 만 제거 하시겠습니까? 즉, 원래의 벡터가'{ "사과", "사과", "오렌지", "사과", "포도"}'와 같이 보이면 그 결과가 {{ "사과", "오렌지", "사과" , "포도"}'또는'{ "사과", "오렌지", "포도"}'? – celtschk

답변

5

어떻게 임시 컨테이너를 사용하는 방법에 대한 :

std::vector<int>::iterator i , j ; 
std::set<int> t_set; 
for(i = v.begin() , j = v.begin() ; i != v.end() ; ++i) 
    if(t_set.insert(*i).second) 
     *j++ = *i ; 
v.erase(j , v.end()); 

std::remove_if 내가 생각할 수

std::set<int> t_set; 
std::vector<int> res; //Resultant vector 

remove_copy_if(v.begin(), v.end(), std::back_inserter(res), 
    [&t_set](int x){ 
     return !t_set.insert(x).second; 
    }); 
+1

+1, 제가 솔기가 낀 거의 동일한 해결책을 게시했습니다. 이것은 가장 빠릅니다 (O (n log n)). –

+0

@LeonidVolnitsky : D – P0W

+0

개체를 복사하는 데 비용이 많이 드는 경우 (문자열에 대한 질문에서 해당 문자의 길이를 말하지 않음) 사용자 지정 비교 함수를 사용하여 반복기를 집합의 원본 벡터에 저장할 수도 있습니다 반복자를 역 참조합니다. 또한, 값싼 swap을 가지고 있다면 할당 대신 swap을 사용할 수있다. C++ 11에서는 이동 할당이 확실한 선택이 될 것입니다. – celtschk

1

이 작업을 수행 할 수 있습니다 :

std::vector<int> v = { 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 8 }; 
// 1 2 2 3 4 5 6 7 8 9 8 

for(size_t i=0;i<v.size();i++) 
{ 
    for(size_t j=0;j<v.size();j++) 
    { 
     if(v[i] == v[j] && i != j) 
     { 
       v.erase(v.begin()+j); 
       j--; // Fix for certain datasets ie: 
     }   //        1 2 1 1 
    } 
} 

// Produces: 
// 1 2 3 4 5 6 7 8 9 
+0

값을 처음으로 생성하지 않으려면 std :: remove의 첫 번째 인수로 현재 반복기 + 1을 전달해야합니다. –

+0

감사합니다. 이것은 올바른 해결책을 제시했습니다. – Quoros

+0

잠깐, 당신이 바꿨습니다. 'erase' 문에서 왜'j'에 1을 더했을까요? –

2

그런 다음 원래 벡터 반복, 하늘의 배열을 생성하고 벡터의 각 항목의 첫 번째 인스턴스를 복사 만 할 수있다. 벡터에 항목을 추가했는지 여부를 추적 할 수 있습니다. 항목을 벡터에 추가하고 새로운 배열에 추가하기 전에 세트의 항목 존재 여부를 확인합니다.

1

std::vector<int>::iterator it; 
it = std::unique (myvector.begin(), myvector.end()); 

이 반복자가 요소를 가리 킵니다 옆에있는 마지막 요소에 대한 간단한 솔루션입니다. 필요하지 않으면이 반복자를 사용할 수 없습니다.

추가 참조 THIS를 참조

편집 : 벡터 정렬 할 것이라고 생각으로

, 새로운 솔루션이 될 수 :

vector<int> vec= {5,1,2,3,5,4,2,1,1,4,3,2,4,5,2,1,3,5,2,3,5,2,3,2,3,5,2,1,3}; 
    set<int> s; 
    vector<int>::iterator vecIter=vec.begin(); 
    vector<int>::iterator vecIterCopy; 
    for(;vecIter!=vec.end(); vecIter++) 
    { 
     if(s.find(*vecIter)==s.end()) 
     { 
      s.insert(*vecIter); 
      *vecIterCopy++ = *vecIter; 
     } 
    } 
+2

그 때문에 벡터를 정렬해야합니다 (적어도 모든 복사본이 연속적이어야 함). 임의 벡터의 순서는 유지할 수 없습니다. –

+0

오, 내 잘못입니다. 나는 그 명령을 분류 된 것으로 해석했다. – Saksham

+0

@MikeSeymour Sorting은 받아 들인 답과 같은 복잡성을 줄 수있는 nlogn을 필요로합니다. – BartoszKP

1

O (n 개의 * 로그 (N)) 솔루션 : std::remove_copy_if

vector<string> V={"aa","bb","aa","cc","cc"}; 
set<string> S; 

auto i=V.begin(); 
auto j=i; 

for(; i!=V.end(); ++i) { 
    if(S.insert(*i).second && i!=j++) 
     *j = std::move(*i); 
} 

V.erase(j,V.end()); 

또한 수정 POW의 버전. 그러나 임시 외적으로 여기에 :

관련 문제