Как удалить повторяющиеся строки / данные в векторе?

ИЗДАНО ВНИЗУ

Если вам интересно, как это сделать, прочитайте принятый ответ, он отлично работает

Итак, я пытался выяснить это в течение пары дней, я прочитал ответы множества людей, но по какой-то причине у меня продолжает появляться ошибка компиляции, когда я пытаюсь удалить дубликаты в моей программе ниже. Есть ли особый способ удалить эти дубликаты из-за того, как я настроил вектор? Пожалуйста, помогите, я очень расстроен, что не могу понять это.

//libraries
#include <iostream>
#include <string>
#include <set>
#include <fstream>
#include <vector>
#include <list>
#include <algorithm>

//class
class Name_Sorter
{
private:
//none
public:
//Name_Sorter();
//~Name_Sorter();
std::string name;
void get_Names(std::string person_Name ){ name = person_Name; }
void output_Names();

};

//get the user file
std::string get_File()//get input file
{
std::ifstream fin;
std::string file_To_Open;

std::cout << "What is the name of the file where you have stored the names? ";
getline(std::cin, file_To_Open);

//std::cout << file_To_Open; // for testing

return file_To_Open;
}
//output
void Name_Sorter::output_Names()
{
std::cout << "Name: " << name << std::endl;
}

//sort
bool comp(const Name_Sorter &t1, const Name_Sorter &t2)  //definition
{
return t1.name < t2.name;
}//compare function

//main program
int main(int argc, const char * argv[])
{
//variables and vector
std::vector<Name_Sorter> info;
std::string names;
std::string file_To_Open;
std::ifstream fin;
int nameCounter = 0;

Name_Sorter *name_Data;//get the file
file_To_Open = get_File();
fin.open(file_To_Open.c_str());
if (!fin.good()) throw "I/O Error";

//get name
while(!fin.eof())
{
fin >> names;
fin.ignore(1000, 10);

name_Data = new Name_Sorter;
name_Data -> get_Names(names);
info.push_back(*name_Data);
delete name_Data;//MM
nameCounter++;
}//get names

fin.close();

//sorting through the vector by name
std::sort(info.begin(), info.end(), comp);

//delete duplicates ****Seems to be a problem here****
info.erase(std::unique(info.begin(), info.end()), info.end());

std::vector<Name_Sorter>::iterator iter;

//transverse vector for output
for ( iter = info.begin(); iter != info.end(); ++iter)
{
/*for(int i = 0; i < nameCounter; i++)
{
erase(info.begin(), info.end(), info.end())
}*/
iter -> output_Names();
}//outputreturn 0;
}//main

И вот сообщение об ошибке:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:658:97:
Недопустимые операнды в двоичном выражении (‘const Name_Sorter’ и ‘const
Name_Sorter ‘)

и где сообщение об ошибке ссылается на:

template <class _T1>
struct __equal_to<_T1, _T1>
{
_LIBCPP_INLINE_VISIBILITY bool operator()(const _T1& __x, const _T1& __y) const {return __x == __y;}
};

Итак, я больше не получаю сообщение об ошибке, однако, когда я добавляю оператор ==, как предлагается, функция удаляет ВСЕ дубликаты из вектора, а не только все дубликаты, кроме одного. Если ввод «Hunter, Hunter, Hunter, Toby, Diane, Kiera», я хотел, чтобы он вывел «Diane, Hunter, Kiera, Toby», и пока он будет просто выводить «Diane, Kiera, Toby»

bool operator== (const Name_Sorter &t1, const Name_Sorter &t2)
{
return t1.name < t2.name;
}

Надеюсь, это может в конечном итоге помочь гораздо большему количеству людей, пытающихся научиться делать это, а не только мне.

0

Решение

std::unique использования operator== по умолчанию. Вы не передаете функцию сравнения, как при вызове std::sort,

Либо определите компаратор и исправьте вызов std::unique, как это:

bool eqComp (const Name_Sorter &t1, const Name_Sorter &t2)
{
return t1.name == t2.name;
}

info.erase(std::unique(info.begin(), info.end(), eqComp), info.end());
//                            include comparator ^^^^

Или, что еще лучше, просто перегрузить operator== для вашего типа:

bool operator== (const Name_Sorter &t1, const Name_Sorter &t2)
{
return t1.name == t2.name;
}

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

Точно так же вы можете перегрузить operator< сделать ваш std::sort позвонить проще:

bool operator< (const Name_Sorter &t1, const Name_Sorter &t2)
{
return t1.name < t2.name;
}

std::sort(info.begin(), info.end());
2

Другие решения

Быстрое предложение, основанное на том, что делает ваш код:

  1. Избавляться от Name_Sorter — это не добавляет никакой ценности — замените его просто на std::string,
  2. Прекратить использование std::vector и использовать std::set вместо. Он будет автоматически сортировать и отсеивать дубликаты при добавлении к нему каждого элемента. Кажется, нет никаких причин, по которым вы не можете его использовать, и это избавляет от всего кода дедупликации / сортировки.
1

Лучший способ сделать это — использовать vector, sort + unique, если речь идет о производительности.

sort( vec.begin(), vec.end() );
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );

Много других способов сделать то же самое можно найти Вот

0

В Name_Sorter вам нужно определить:

bool operator==(const Name_Sorter& a)
0

На мой взгляд, несколько странных вещей:

  • зачем вызывать функцию get_Name, если эта функция устанавливает имя!
  • Нет конструктора для класса?
  • Способ заполнения вашего вектора: вам не нужен указатель, чтобы сделать это
  • Вам не нужно сортировать свой вектор перед удалением элементов

Исходя из этого, поскольку вектор состоит из пользовательских элементов, вам необходимо либо определить операнд == для вашего класса, либо указать третий аргумент в уникальной функции, которая является функцией comp.
Здесь то же самое -> std :: unique и удаление дубликатов из контейнера объектов

Я быстро переписываю некоторые вещи для вашего кода и больше не получаю ошибок. Я думаю, что это не идеально, но, по крайней мере, лучше

//class
class Name_Sorter
{
private:
//none
public:
Name_Sorter();
//~Name_Sorter();
std::string name;
void set_Names(std::string person_Name ){ name = person_Name; }
std::string get_Names(){ return name; }
void output_Names();

};

Name_Sorter::Name_Sorter() : name("")
{}

//get the user file
std::string get_File()//get input file
{
std::ifstream fin;
std::string file_To_Open;

std::cout << "What is the name of the file where you have stored the names? ";
getline(std::cin, file_To_Open);

//std::cout << file_To_Open; // for testing

return file_To_Open;
}
//output
void Name_Sorter::output_Names()
{
std::cout << "Name: " << name << std::endl;
}

//sort
bool comp(const Name_Sorter t1, const Name_Sorter t2)  //definition
{
return t1.name == t2.name;
}//compare function

//main program
int main(int argc, const char * argv[])
{
//variables and vector
std::vector<Name_Sorter> info;
std::string names;
std::string file_To_Open;
std::ifstream fin;
int nameCounter = 0;//get name
for(int i = 0 ; i < 5 ; i++)
{
Name_Sorter name_Data;
name_Data.set_Names("lolz");
info.push_back(name_Data);
nameCounter++;
}//get names

info.erase(std::unique(info.begin(), info.end() , comp) , info.end()) ;

for(auto i : info){
cout << i.get_Names() << endl;
}

return 0;
}//main
0

std :: unique требует оператора == для сравниваемых типов. Предоставьте такой оператор для вашего класса, и он должен работать

-1
По вопросам рекламы [email protected]