2017-07-29 6 views
2

再帰テンプレートはまだ私にはかなり混乱しています。たとえば、再帰的なテンプレートを使用して、n次元ベクトルの重複メンバーをすべて削除する関数を作成しようとしましたが、動作するコードがいくつかあると思います。私はベースの静的変数として「見える」セット変数を宣言する方法http://coliru.stacked-crooked.com/a/6e11f9ababcdfa12N次元ベクトルの重複メンバーを削除

お知らせ:

template <typename T> 
    void remove_if_duplicate(std::vector<T>& vec, bool at_end) 
    { 
    static std::set<T> seen; 
    if(!at_end) 
    { 
     auto newEnd = std::remove_if(vec.begin(), vec.end(), [=](const T& value) 
     { 
     if(seen.find(value) != std::end(seen)) 
      return true; 

     seen.insert(value); 
     return false; 
     }); 
     vec.erase(newEnd, vec.end()); 
     std::cout << "\n\nhere: " << at_end << "\n\n"; 
    } 
    if(at_end) {seen.clear();} 
    } 

    template <typename T> 
    void remove_if_duplicate(std::vector<std::vector<T>>& v, bool at_end) 
    { 
    if(!at_end) 
    { 
     for(unsigned int i = 0; i < v.size(); i++) 
     { 
     remove_if_duplicate(v[i], at_end); 
     } 
    } 
    if(at_end) {remove_if_duplicate(v[0], at_end);} 
    } 

template <typename T> 
void remove_duplicates(std::vector<std::vector<T>>& v) 
{ 
    remove_if_duplicate(v, false); 
    remove_if_duplicate(v, true); 
} 

は、ここでは例を参照してください。しかし、私はこれを行うには良い方法があることをほとんど確信しています関数。私は多次元ベクトルを反復処理しても以前に見たことのある以前のアイテムにはまだアクセスできるようにこれを行いました。多次元ベクトルがテンプレート化されている基底型がその時点では不明である(そして、一次元ベクトルの場合もどちらもうまくいきません)ので、2番目の関数の中で "見た"変数を宣言することはできません。だから私は、これらの関数にブーリアンを渡して、実際に静的な変数をクリアするときを決めて、この関数を他のn次元のベクトルに使うことができるようにしなければなりません。

これまでのように動作しているように見えますが、私が望むふるまいを与えている間、実装が貧弱なために予期しないバグが表示されるかどうかはわかりません。私はこれをここでやったやり方は理想から遠いと思うし、より良い、より効率的な方法があると確信している。 どうやって違うのですか?

答えて

2

あなたは正しいsetを構築するためにヘルパークラスを使用することにより、静的を取り除くことがあります。

template <typename T> struct inner_type 
{ 
    using type = T; 
}; 

template <typename T> struct inner_type<std::vector<T>> 
{ 
    using type = typename inner_type<T>::type; 
}; 

次に、あなたが行うことができます:

私がセットを使用することはありません
template <typename T> 
void RemoveDuplicatesImpl(std::vector<T>& v, 
          std::set<T>& values) 
{ 
    v.erase(std::remove_if(v.begin(), v.end(), [&](const T& t) 
     { 
      return !values.insert(t).second; 
     }), v.end()); 
} 

template <typename T> 
void RemoveDuplicatesImpl(std::vector<std::vector<T>>& v, 
          std::set<typename inner_type<T>::type>& values) 
{ 
    for (auto& inner : v) { 
     RemoveDuplicatesImpl(inner, values); 
    } 
} 

template <typename T> 
void RemoveDuplicates(std::vector<T>& v) 
{ 
    std::set<typename inner_type<T>::type> values; 
    RemoveDuplicatesImpl(v, values); 
} 
0

すべて。 std::setを使用しているので、合成ベクトルの要素の順序は関係ありません。

template<class T> void RemoveDuplicates(std::vector<T> &v) 
{ 
    std::sort(v.begin(), v.end()); 
    v.erase(v.begin(), std::unique(v.begin(), v.end()); 
} 

template<class T> void RemoveDuplicates(std::vector<std::vector<T> > &v) 
{ 
     // remove duplicates from every individual vector 

     for (auto &i : v) RemoveDuplicates(e); 

     // for every vector, remove any copy of its elements in subsequent vectors 
     auto i = v.begin(); 
     auto end = v.end(); 
     while (i != end) 
     { 
      auto next = std::advance(i, 1); // alternatively next = i+1 
      auto next_i = next; 
      while (next != end) 
      { 
       for (const auto &e : *i) 
        next->erase(next->begin(), std::remove(next->begin(), next->end(), e)); 
       next = std::advance(next, 1);  // alternatively ++next 
      } 
      i = next_i; 
     } 
}