删除N维向量的重复成员

时间:2017-07-29 23:12:53

标签: c++ c++11 templates vector

递归模板对我来说仍然很混乱,我觉得我并不像我应该那样使用它们。例如,我尝试使用递归模板来编写一个函数,该函数将删除n维向量的所有重复成员,我相信我有一些有效的代码。但是,我几乎相信有更好的方法可以做到这一点:

  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);
}

请在此处查看示例:http://coliru.stacked-crooked.com/a/6e11f9ababcdfa12

注意我如何声明set变量&#34; see&#34;作为基函数的静态变量。我已经这样做了,所以我仍然可以访问我以前的所有项目&#34;看到&#34;甚至在迭代多维向量之前。我无法宣布&#34;见过&#34;第二个函数内部的变量,因为多维向量被模板化的基本类型在那一点是未知的(然后单维向量的情况也不会起作用)。那么我必须将布尔值传递给这些函数,以便决定何时实际清除静态集变量,以便我可以再次将此函数用于其他n维向量。

虽然它似乎工作到目前为止并且正在给我我想要的行为,但我不确定是否会因为我的执行不佳而出现任何意外错误。我认为我在这里做到这一点的方式远非理想,我确信这是一种更好,更有效的方法。 你会如何区别?

2 个答案:

答案 0 :(得分: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);
}

答案 1 :(得分: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;
      }
 }