从载体向量中删除重复的载体

时间:2015-12-29 20:32:16

标签: c++ c++11 vector

我正在尝试在Link找到问题的解决方案。

这是我的代码片段

bool compareVec(vector<int> a, vector<int> b) {
    return std::equal(a.begin(), a.end(), b.begin());
}
vector<vector<int> > ans;
ans.erase(std::remove_if(ans.begin(), ans.end(), compareVec), ans.end());

我收到以下错误

/usr/include/c++/4.8/bits/stl_algo.h: In instantiation of 
'_RandomAccessIterator std::__find_if(_RandomAccessIterator, 
_RandomAccessIterator, _Predicate, std::random_access_iterator_tag) [with 
_RandomAccessIterator = __gnu_cxx::__normal_iterator<std::vector<int>*, 
std::vector<std::vector<int> > >; _Predicate = bool (*)(std::vector<int>, 
std::vector<int>)]':

/usr/include/c++/4.8/bits/stl_algo.h:4465:41:   required from '_IIter   
std::find_if(_IIter, _IIter, _Predicate) [with _IIter = 
__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int>
 > >; _Predicate = bool (*)(std::vector<int>, std::vector<int>)]'

/usr/include/c++/4.8/bits/stl_algo.h:1144:64:   required from '_FIter 
std::remove_if(_FIter, _FIter, _Predicate) [with _FIter = 
__gnu_cxx::__normal_iterator<std::vector<int>*, std::vector<std::vector<int> 
> >; _Predicate = bool (*)(std::vector<int>, std::vector<int>)]'

solution.cpp:40:64:   required from here
/usr/include/c++/4.8/bits/stl_algo.h:214:23: error: too few arguments to    
function
if (__pred(*__first))
                   ^
/usr/include/c++/4.8/bits/stl_algo.h:218:23: error: too few arguments to   
function
if (__pred(*__first))
                   ^
/usr/include/c++/4.8/bits/stl_algo.h:222:23: error: too few arguments to 
function
if (__pred(*__first))
                   ^

任何人都可以帮我调试吗? 提前致谢

修改

对矢量元素进行排序,并对所有这些矢量进行排序。

Unique也会出错。我无法弄明白为什么?

为什么我提供的链接中给出了示例,这里没有帮助?

2 个答案:

答案 0 :(得分:2)

std::remove_if需要一元谓词。您传递二进制谓词,这会导致您的错误(/usr/include/c++/4.8/bits/stl_algo.h:222:23: error: too few arguments to function→您的函数需要两个参数,而不是一个)。 此外,std::remove_if执行其删除而不考虑其他元素(这就是为什么它接受一元谓词),因此它实际上并不是您要查找的内容。

您要使用的是std::unique,其中 需要您已实施的compareVec。但是,std::vector已经提供operator==重载,因此实现实际上是多余的!另外,您说使用std::unique时出错。尝试将参数传递为const&

因此,当您的外部向量和内部向量已经排序时,解决方案就像任何其他已排序元素向量一样:

outer.erase(std::unique(outer.begin(), outer.end()), outer.end());

答案 1 :(得分:1)

好的,因为这没有用C ++ 11标记,我将使用仿函数而不是lambda。

你遇到的第一个问题是remove_if采用了UnaryPredicate,这意味着它只能接受一个参数。

第二个问题也与您对remove_if的理解有关。修复compareVec只接受一个参数后,你就会想知道如何将所有元素相互比较。

您可以采用以下两种方式之一:

  • 对向量矢量进行排序(<运算符按字典顺序定义vector),然后使用std::uniqueExamples)(More examples)。
    • 在您提供的链接中(与我刚刚链接的链接相同),请注意它们首先排序,而您没有排序。
  • 或者,如果您的元素没有<的明确定义,只有==,则可以对每个后续项目执行O(N 2 )查找/擦除(如下所示):

比较函子(可以在C ++ 11及更高版本中作为lambda使用)

struct CompareVec
{
    CompareVec(const std::vector<int>& _in) : compare_against(_in){}

    bool operator()(const std::vector<int>& rhs) const
    {
        return compare_against == rhs;
    };

    const std::vector<int>& compare_against;
};

如此使用:

for (size_t i = 0; i < ans.size(); ++i)
{
    CompareVec comparator(ans[i]);
    ans.erase(std::remove_if(ans.begin()+i+1, ans.end(), comparator), ans.end());
}

Live Demo(在C ++ 11中编译,因为不想用初始化列表初始化测试向量)

修改

在C ++ 11中,我们可以摆脱CompareVec仿函数并用lambda替换它:

for (size_t i = 0; i < ans.size(); ++i)
{
    ans.erase(std::remove_if(ans.begin()+i+1, ans.end(), 
    [&ans, &i](const std::vector<int>& _rhs)
    { 
        return ans[i] == _rhs;
    }) , ans.end());
}

Demo2