Search code examples
c++vectorstd-pair

What is the simplest way to remove duplicates in vector<pair<A,A> > if {x,y} and {y,x} are also considered as identical?


Is there built in method to remove duplicates of pair vector if 2 pairs, {x,y} and {y,x} are also considered as duplicate?

for example,if I have vector like it:

{{1,2},{4,3},{2,1},{5,6},{1,2},{3,4},{0,1}}

I want to remove duplicate to become:

{{1,2},{4,3},{5,6},{0,1}}

is there any built in function to handle the case that {x,y} and {y,x} are identical?

If not, what is the simplest way to do this?

I considered to use for loop something like that but not works:

vector<int> isRemove;
int count=0;
for(pair<int,int> a : p){
    isRemove.push_back(0);
    for(pair<int,int> b : p){
        if((a.first==b.first && a.second==b.second) || (a.first==b.second && a.second==b.first)){
            isRemove[count]=1;
            break;
        }
    }
    count++;
}
for(int i=isRemove.size()-1;i>=0;i--){
    printf("%d\n",isRemove[i]);
    if(isRemove[i]){
        p.erase(p.begin()+i);
    }
}

is there any simpler method else?


Solution

  • std::set holds unique values. Uniqueness is determined by a comparator. You can implement your desired solution as follows (live example):

    #include <algorithm>
    #include <iostream>
    #include <set>
    #include <vector>
    
    struct custom_comparator {
        bool operator()(const std::pair<int, int>& a,
                        const std::pair<int, int>& b) const
        {
            return less_comparator(std::minmax(a.first, a.second),
                                   std::minmax(b.first, b.second));
        }
    
        std::less<std::pair<int, int>> less_comparator;
    };
    
    int main() {
        // Input data including some duplicates
        std::vector<std::pair<int, int>> a = {
            {1, 2}, {4, 3}, {2, 1}, {5, 6}, {5, 6}, {6, 5}, {1, 2}, {3, 4}, {0, 1}
        };
    
        // Specify custom comparator for the set
        std::set<std::pair<int, int>, custom_comparator> unique;
    
        // Fill the set
        for (const auto& p : a) {
            unique.insert(p);
        }
    
        // Demonstrate uniqueness by outputting the elements of the set
        for (const auto& p : unique) {
            std::cout << p.first << ", " << p.second << "\n";
        }
    
        return 0;
    }
    

    Output:

    0, 1
    1, 2
    4, 3
    5, 6
    

    You simply define a set with a custom comparator that ensures a consistent ordering within each pair when calling std::less, then fill the set.