Я пытаюсь реализовать решение проблемы, найденной по ссылке Ссылка .

Вот мой фрагмент кода

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 тоже выдает ошибку. Я не могу понять почему?

Почему пример, приведенный в предоставленной мной ссылке, здесь бесполезен?

0
LearningToCode 29 Дек 2015 в 23:32

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());
3
Brian Rodriguez 2 Янв 2016 в 19:06

Хорошо, поскольку это не отмечено C ++ 11, я буду использовать функтор вместо лямбды.

Первая проблема заключается в том, что remove_if принимает UnaryPredicate, что означает, что он должен принимать только один аргумент.

Вторая проблема также связана с вашим пониманием remove_if. После того, как вы исправите compareVec, чтобы он принимал только один аргумент, вам остается только гадать, как можно сравнить все элементы друг с другом.

Вы можете подойти к этому одним из двух способов:

  • Отсортируйте вектор векторов (оператор < определен лексикографически для vector), а затем используйте std::unique (Примеры) (Дополнительные примеры).
    • В предоставленной вами ссылке (такой же, как та, на которую я только что указал), обратите внимание, что они сортируются первыми, а вы - нет.
  • Или, если нет четкого определения < для ваших элементов, только ==, вы можете выполнить поиск / стирание O (N 2 ) для каждого последующего элемента (показано ниже ):

Функтор сравнения (может использоваться как лямбда в C ++ 11 и выше)

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 и заменить его лямбдой:

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

Демо2

2
Community 23 Май 2017 в 11:44