【问题标题】:Delete Duplicate Members of N-Dimensional Vector删除 N 维向量的重复成员
【发布时间】:2018-01-05 18:53:28
【问题描述】:

递归模板对我来说仍然很困惑,而且我觉得我没有像我应该的那样使用它们。例如,我尝试使用递归模板编写一个函数,该函数将删除 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 变量“seen”声明为基本函数的静态变量。我这样做是为了即使在迭代多维向量时仍然可以访问我之前“看到”的先前项目。我不能在第二个函数中声明“seen”变量,因为多维向量模板化的基本类型在那时是未知的(然后单维向量的情况也不起作用)。因此,我必须将布尔值传递给这些函数,以便决定何时实际清除静态集变量,以便我可以再次将此函数用于其他 n 维向量。

虽然到目前为止它似乎工作并给了我想要的行为,但我不确定是否会由于我的糟糕实施而出现任何意外错误。我认为我在这里所做的方式远非理想,而且我确信有更好、更有效的方式。 你会怎么做?

【问题讨论】:

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


    【解决方案1】:

    您可以通过使用帮助类来构造正确的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);
    }
    

    【讨论】:

      【解决方案2】:

      我根本不会使用套装。由于您使用的是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;
            }
       }
      

      【讨论】:

        猜你喜欢
        • 2021-06-12
        • 2011-01-31
        • 1970-01-01
        • 2011-11-29
        • 2018-07-30
        • 1970-01-01
        • 2023-01-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多