【问题标题】:How do you delete duplicate strings/data in a vector?如何删除向量中的重复字符串/数据?
【发布时间】:2015-04-22 09:47:49
【问题描述】:

在底部编辑

如果您想知道如何做到这一点,请阅读接受的答案,它可以完美运行

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

//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: 二进制表达式的无效操作数('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;}
};

好的,所以我不再收到错误消息,但是当我按照建议添加 operator== 时,该函数似乎从向量中删除了所有重复项,而不仅仅是除一个之外的所有重复项。如果输入是“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== 来比较元素。您需要为 _T1& 定义它
  • 请参阅 TartanLlama 的更新答案。您的 operator== 应该比较 t1.name == t2.name 以实现平等。
  • 你的 operator== 这样做:t1.name &lt; t2.name - 这不是一个相等运算符。你所拥有的是一个小于运算符。
  • 是的,我看到了,谢谢大家!这几天我真的很困惑。最初的任务是为一个类和手动遍历数组,我可以做得很好,但我总是想了解更多,所以我决定尝试自己使用一个向量。即使我不明白为什么,它现在也能完美运行——我将在明天/接下来的几个月里阅读运营商及其功能。

标签: c++ vector data-storage


【解决方案1】:

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&lt; 以使您的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。当每个项目附加到它时,它将自动排序并清除重复项。您似乎没有理由不能使用它,它消除了所有重复数据删除/排序代码。

【讨论】:

  • 这本来是我班级的一个问题,但是使用数组并手动遍历它们很容易——我想尝试自己使用向量来了解更多关于它们的信息。不过,我现在会去阅读有关设置的信息,感谢您提供的信息,一切都会有所帮助。
【解决方案3】:

就性能而言,最好的方法是使用vector、sort + unique。

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

可以找到许多其他相同的方法here

【讨论】:

  • OP 知道如何做到这一点,请参阅代码。请查看错误消息。
【解决方案4】:

在 Name_Sorter 中你需要定义:

bool operator==(const Name_Sorter& a)

【讨论】:

    【解决方案5】:

    在我看来,有几件事很奇怪:

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

    除此之外,由于向量是由自定义元素组成的,因此您需要为您的类定义 == 操作数,或者在函数 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
    

    【讨论】:

    • std::unique 算法会移除连续重复项,因此需要事先对向量进行排序,使其移除所有重复项
    【解决方案6】:

    std::unique 需要 operator== 用于比较类型。为您的课程提供这样的运算符,它应该可以工作

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-29
      • 2015-06-07
      • 1970-01-01
      • 2018-05-18
      • 1970-01-01
      相关资源
      最近更新 更多