ИЗДАНО ВНИЗУ
Если вам интересно, как это сделать, прочитайте принятый ответ, он отлично работает
Итак, я пытался выяснить это в течение пары дней, я прочитал ответы множества людей, но по какой-то причине у меня продолжает появляться ошибка компиляции, когда я пытаюсь удалить дубликаты в моей программе ниже. Есть ли особый способ удалить эти дубликаты из-за того, как я настроил вектор? Пожалуйста, помогите, я очень расстроен, что не могу понять это.
//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;
}
Надеюсь, это может в конечном итоге помочь гораздо большему количеству людей, пытающихся научиться делать это, а не только мне.
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());
Быстрое предложение, основанное на том, что делает ваш код:
Name_Sorter
— это не добавляет никакой ценности — замените его просто на std::string
,std::vector
и использовать std::set
вместо. Он будет автоматически сортировать и отсеивать дубликаты при добавлении к нему каждого элемента. Кажется, нет никаких причин, по которым вы не можете его использовать, и это избавляет от всего кода дедупликации / сортировки.Лучший способ сделать это — использовать vector, sort + unique, если речь идет о производительности.
sort( vec.begin(), vec.end() );
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );
Много других способов сделать то же самое можно найти Вот
В Name_Sorter вам нужно определить:
bool operator==(const Name_Sorter& a)
На мой взгляд, несколько странных вещей:
Исходя из этого, поскольку вектор состоит из пользовательских элементов, вам необходимо либо определить операнд == для вашего класса, либо указать третий аргумент в уникальной функции, которая является функцией 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
std :: unique требует оператора == для сравниваемых типов. Предоставьте такой оператор для вашего класса, и он должен работать