如何删除向量中的重复项 strings/data?
How do you delete duplicate strings/data in a vector?
已在底部编辑
如果您想知道如何执行此操作,请阅读已接受的答案,它非常有效
好吧,我这几天一直在努力解决这个问题,我已经阅读了很多人的回答,但出于某种原因,当我尝试删除我的重复项时,我一直遇到编译错误下面的程序。由于我如何设置向量,是否有一种特殊的方法需要删除这些重复项?请帮助,我感到非常沮丧,因为我无法解决这个问题。
//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();
}//output
return 0;
}//main
下面是错误信息:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:658:97:
Invalid operands to binary expression ('const Name_Sorter' and '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;
}
希望这最终可以帮助更多尝试学习如何做到这一点的人,而不仅仅是我。
就性能而言,最好的方法是使用 vector、sort + unique。
sort( vec.begin(), vec.end() );
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );
可以找到许多其他相同的方法here
在Name_Sorter中你需要定义:
bool operator==(const Name_Sorter& a)
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());
std::unique 需要 operator== 比较类型。为您的 class 提供这样的运算符,它应该可以工作
根据您的代码的作用给出的快速建议:
- 摆脱
Name_Sorter
- 它没有增加任何价值 - 只需将其替换为 std::string
。
- 停止使用
std::vector
,改用 std::set
。当每个项目附加到它时,它会自动排序并清除重复项。您似乎没有理由不使用它,它摆脱了所有重复数据删除/排序代码。
在我看来,有几件事很奇怪:
- 为什么要调用函数 get_Name 如果此函数正在设置名称!
- class 没有构造函数?
- 填充向量的方式:你不需要指针来做到这一点
- 您不需要在擦除元素之前对矢量进行排序
除此之外,由于矢量由自定义元素组成,您需要为 class 定义 == 操作数或在函数 unique 中指定第三个参数,这是您的 comp 函数。
这里也是一样 --> std::unique and removing duplicates from a container of objects
我很快为你的代码重写了一些东西,我再也没有出错了。我想它并不完美,但至少更好
//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
已在底部编辑
如果您想知道如何执行此操作,请阅读已接受的答案,它非常有效
好吧,我这几天一直在努力解决这个问题,我已经阅读了很多人的回答,但出于某种原因,当我尝试删除我的重复项时,我一直遇到编译错误下面的程序。由于我如何设置向量,是否有一种特殊的方法需要删除这些重复项?请帮助,我感到非常沮丧,因为我无法解决这个问题。
//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();
}//output
return 0;
}//main
下面是错误信息:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/algorithm:658:97: Invalid operands to binary expression ('const Name_Sorter' and '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;
}
希望这最终可以帮助更多尝试学习如何做到这一点的人,而不仅仅是我。
就性能而言,最好的方法是使用 vector、sort + unique。
sort( vec.begin(), vec.end() );
vec.erase( unique( vec.begin(), vec.end() ), vec.end() );
可以找到许多其他相同的方法here
在Name_Sorter中你需要定义:
bool operator==(const Name_Sorter& a)
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());
std::unique 需要 operator== 比较类型。为您的 class 提供这样的运算符,它应该可以工作
根据您的代码的作用给出的快速建议:
- 摆脱
Name_Sorter
- 它没有增加任何价值 - 只需将其替换为std::string
。 - 停止使用
std::vector
,改用std::set
。当每个项目附加到它时,它会自动排序并清除重复项。您似乎没有理由不使用它,它摆脱了所有重复数据删除/排序代码。
在我看来,有几件事很奇怪:
- 为什么要调用函数 get_Name 如果此函数正在设置名称!
- class 没有构造函数?
- 填充向量的方式:你不需要指针来做到这一点
- 您不需要在擦除元素之前对矢量进行排序
除此之外,由于矢量由自定义元素组成,您需要为 class 定义 == 操作数或在函数 unique 中指定第三个参数,这是您的 comp 函数。 这里也是一样 --> std::unique and removing duplicates from a container of objects
我很快为你的代码重写了一些东西,我再也没有出错了。我想它并不完美,但至少更好
//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