2010-12-07 2 views
2

벡터처럼 중첩되지 않은 컨테이너에서 삭제할 때, 나는 다음과 같은 것을하고있다.중첩 된 컨테이너에서 삭제하기 위해 지우기를 삭제 하시겠습니까? (바깥 쪽 삭제, C++ STL)

struct is_to_remove 
{ 
    is_to_remove(dynamic_bitset<>& x) : x(x) {} 
    const bool operator()(unsigned int id) 
    { 
     return x[id]; 
    } 

private: 
    dynamic_bitset<> x; 
}; 

inline static void remove_elements_in_vector(vector<unsigned int>& vec, boost::dynamic_bitset<>& to_remove) 
{ 
    // use the erase-remove idiom to remove all elements marked in bitset 
    vec.erase(remove_if(vec.begin(), vec.end(), is_to_remove(to_remove)), vec.end()); 
} 

이것은 소위 erase-remove idiom이다.

이제, 두 번째 데이터 구조 vector<vector<unsigned int> > 또는 deque<vector<unsigned int> >, 어디 비트 집합에 따라 자체 내부 컨테이너의 외부 컨테이너 요소를 삭제하려면 원하는.

  • 이 중첩 된 컨테이너 유형에 지우기 제거 관용구를 사용할 수 있습니까?
  • 그렇다면 어떻게 가능합니까?
  • 제한 사항이 있습니까? (예 : vec의 vec는 가능하지만 vec의 deque는 아닙니다)?

내 첫 번째 순진한 접근 방식은 다음과 같습니다. 나는 remove_if가 요소를 순차적으로 반복하고 순차적으로 요소를 결정하고 하나씩 결정한다고 가정했습니다. 그것은 잘못된 가정입니까?

struct is_to_remove_new 
{ 
    is_to_remove_new(dynamic_bitset<>& x, unsigned int index) : x(x), index(index) {} 
    const bool operator()(vector<unsigned int> & vec) 
    { 
     return x[index++]; 
    } 

private: 
    dynamic_bitset<> x; 
    unsigned int index; 
}; 

inline static void remove_elements_in_vectorvector(vector<vector<unsigned int> >& vec, boost::dynamic_bitset<>& to_remove) 
{ 
    // use the erase-remove idiom to remove all elements marked in bitset 
    vec.erase(remove_if(vec.begin(), vec.end(), is_to_remove_new(to_remove, 0)), vec.end()); 
} 

결과가 잘못되었습니다. 따라서 올바른 해결책을 찾고 있습니다. 나는 내가 보장하지 않는 몇 가지 것을 추측했다고 생각한다. 나에게 기본 질문은 다음과 같다. 제거 할 것인지를 검사 할 내부 컨테이너의 ID를 얻는 방법..
위의 게시 된 순진한 접근 방식은 순차적 처리를 계산하고 가정합니다.

귀하의 도움에 감사드립니다.

Sascha

업데이트 및 경고

벡터 벡터의 경우 Stas 솔루션이 잘 작동합니다. 그러나 deque가 인접한 방식으로 저장되지 않기 때문에이 솔루션은 벡터 deque에 대해 작동하지 않을 것이라고 생각합니다. 이는 펑터에서 인덱스 계산이 실패 함을 의미합니다.

누구든지 확인할 수 있습니까?

답변

3

어떤 요소가 벡터에 포함되는지는 중요하지 않습니다. 제거해야 할 항목을 정의하면 제거됩니다.

앞에서 말한 것처럼 질문은 벡터에서 요소를 식별하는 방법입니다. 가장 확실한 대답은 색인 [0; vector_size - 1]입니다.

벡터 덕분에 요소 자체로 쉽게 요소 색인을 얻을 수 있습니다.

std::vector<std::string> vec; 
vec.push_back("zero"); 
vec.push_back("one"); 
vec.push_back("two"); 

std::string& elem = vec[2]; 
int index = std::distance(&vec[0], &elem); // get element index by element itself 
// index == 2 

따라서 벡터 요소를 remove_if 알고리즘 조건부의 인덱스로 쉽게 식별 할 수 있습니다. 다음 예제를 살펴보십시오.그것은 꽤 바보와 std::bitset<6>를 하드 코딩 사용하는 것입니다, 그러나 이것은 단지 그림 :

#include <vector> 
#include <string> 
#include <bitset> 

struct ToRemove 
{ 
    ToRemove(std::vector<std::string>& vec, const std::string& mask) 
    : m_vec(vec) 
    , m_mask(mask) 
    {} 

    bool operator()(std::string& obj) 
    { 
     const int index = std::distance(&m_vec[0], &obj); 
     return m_mask[index]; 
    } 

    std::vector<std::string>& m_vec; 
    std::bitset<6> m_mask; 
}; 

사용

int main (int argc, char const *argv[]) 
{ 
    std::vector<std::string> vec; 
    vec.push_back("zero"); 
    vec.push_back("one"); 
    vec.push_back("two"); 
    vec.push_back("three"); 
    vec.push_back("four"); 
    vec.push_back("five"); 

    std::string mask = ("010011"); // Remove "zero", "one" and "four" 
    vec.erase(remove_if(vec.begin(), vec.end(), ToRemove(vec, mask)), vec.end()); 

    for (unsigned i = 0; i < vec.size(); ++i) 
    { 
     std::cout << vec[i] << " "; 
    } 
    std::cout << std::endl; 

    return 0; 
} 

결과 마법처럼

two three five 
+0

작품. 고맙습니다. 시도 할 다음 작업 : 벡터 :-)을 사용하여이 작업을 수행하십시오. – sascha

+0

더 많은 테스트 후,이 솔루션은 외부 벡터 (연속 보증이 유지되는 경우)에서 작동하지만 외부 큐가 아닌 경우 작동한다고 생각합니다. anybode가 그것을 확인할 수 있습니까? 나는 deque의 non-contiguous 속성 때문에 functor에서 계산 된 인덱스가 잘못되었다고 생각합니다 -> error. – sascha