如何删除向量中的重复字符串/数据?

时间:2015-04-22 09:47:49

标签: c++ vector data-storage

在底部编辑

如果您想知道如何做到这一点,请阅读已接受的答案,它完美无缺

好的,所以我一直试图解决这个问题几天,我已经阅读了很多人的答案但是由于某种原因,当我尝试在我的程序中删除重复项时,我不断收到编译错误。有没有一种特殊的方法,我需要删除这些重复项,因为我如何设置向量?请帮助,我非常沮丧,我无法弄清楚这一点。

//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 /算法: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;
}

希望这最终可以帮助更多人尝试学习如何做而不仅仅是我。

6 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

根据您的代码似乎做的快速建议:

  1. 摆脱Name_Sorter - 它没有增加任何价值 - 只需使用std::string替换它。
  2. 停止使用std::vector并改为使用std::set。它将自动排序并清除重复项,因为每个项目都附加到它上面。似乎没有理由你不能使用它,它摆脱了所有的重复数据删除/排序代码。

答案 2 :(得分:0)

这样做的最佳方法是使用vector,sort + unique就性能而言。

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

可以找到许多其他方法here

答案 3 :(得分:0)

在Name_Sorter中,您需要定义:

bool operator==(const Name_Sorter& a)

答案 4 :(得分:0)

在我看来,有些事情很奇怪:

  • 如果此函数正在设置名称,为什么要调用函数get_Name!
  • 没有类的构造函数?
  • 填充向量的方法:你不需要指针来做那个
  • 在删除元素之前,您无需对矢量进行排序

从那里开始,因为向量是自定义元素的组合,你需要为你的类定义==操作数或在函数unique中指定第三个参数,这是你的comp函数。 这里也一样 - &gt; 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

答案 5 :(得分:-1)

对于比较类型,

std :: unique需要operator ==。为您的班级提供这样的操作员,它应该工作