std::unique and removing duplicates from a container of objects

折月煮酒 提交于 2019-12-04 09:10:01

Two options to be able to use std::unique:

  1. Define an operator== method for Packet and change the vector<Packet*> to vector<Packet>.

    bool Packet::operator==(const Packet& rhs) const
    {
        if (getFilingTime() != rhs.getFilingTime())
            return false;
        if (getSpid() != rhs.getSpid())
            return false;
        return true;
    }
    
    //etc.
    
    int main()
    {
        vector<Packet> pkts;
        pkts.push_back(Packet("10:20", "1004"));
        pkts.push_back(Packet("10:20", "1004")); // not unique (duplicate of the line above)
        pkts.push_back(Packet("10:20", "251"));
        pkts.push_back(Packet("10:20", "1006"));
    
        // remove packet from vector if time and ID are the same
    
         pkts.erase(unique(pkts.begin(), pkts.end()), pkts.end());                   
    
        return 0;
    }
    
  2. Keep the vector as vector<Packet*> and define a method to compare the elements.

    bool comparePacketPtrs(Packet* lhs, Packet* rhs)
    {
        if (lhs->getFilingTime() != rhs->getFilingTime())
            return false;
        if (lhs->getSpid() != rhs->getSpid())
            return false;
        return true;
    }
    
    //etc.
    
    int main()
    {
        vector<Packet*> pkts;
        pkts.push_back(new Packet("10:20", "1004"));
        pkts.push_back(new Packet("10:20", "1004")); // not unique (duplicate of the line above)
        pkts.push_back(new Packet("10:20", "251"));
        pkts.push_back(new Packet("10:20", "1006"));
    
        // remove packet from vector if time and ID are the same
    
         pkts.erase(unique(pkts.begin(), pkts.end(), comparePacketPtrs), pkts.end());                   
    
        return 0;
    }
    

As an alternative to unique, you could simply insert the elements into a set (or unordered_set in C++11).

Whichever way you decide to go, you'll need to define comparison operators for Packet. For unique, you'll need operator==; for set you'll need operator<. For completeness, you should define both, and their counterparts:

class Packet {
    …
    bool operator==(const Packet& p) const {
        return fillingTime == p.fillingTime && recordID == p.recordID;
    }
    bool operator<(const Packet& p) const {
        return fillingTime < p.fillingTime ||
               (fillingTime == p.fillingTime && recordID < p.recordID);
    }
    bool operator!=(const Packet& p) const { return !(*this == p); }
    bool operator> (const Packet& p) const { return p < *this; }
    bool operator>=(const Packet& p) const { return !(*this < p); }
    bool operator<=(const Packet& p) const { return !(p < *this); }
    …
};

If you use C++11's unordered_set, you'll need to go one step further and define a hash function.

EDIT: I just noticed you're storing pointers to Packet. Why? Just store Packet directly.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!