2010-12-07 25 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です。

今、私は、ビットセットに応じて外側のコンテナ要素(内部の型のコンテナ)を削除したい、2番目のデータ構造体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

更新と警告

ベクトルoベクトルの場合、 Stasソリューションは素晴らしい動作をしています。しかし、私はデキューが連続した方法で保存されていないので、このソリューションはベクトルのデキューでは機能しないと思います。これは、ファンクタ内のインデックスの計算が失敗することを意味します。

誰でもそれを確認できますか?

答えて

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はそれを確認できますか?私は、両端キューの非連続性のため、ファンクタの計算インデックスが間違っていると思います - >エラーです。 – sascha

関連する問題