c++algorithmstlset-union

std::set_union vector<pair<string,string>>


I want to compute the union between two vectors:

std::vector<pair<string,string>> p1;

std::vector<pair<string,string>> p2;

The problem is that why is the union being done on the second element instead of first? the size of the union should be equal to 4. Is it possible to modify set_union so that the Union is done on the first element?


#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;
int main()
{
    std::vector<pair<string,string>> p1;
    std::vector<pair<string,string>> p2;
    p1.push_back(make_pair("A","1"));
    p1.push_back(make_pair("B","2"));
    p1.push_back(make_pair("C","3"));;
    p2.push_back(make_pair("A","4"));
    p2.push_back(make_pair("B","5"));
    p2.push_back(make_pair("C","6"));
    p2.push_back(make_pair("D","7"));
    //sort vectors according to first element
    sort(p1.begin(), p1.end(), [](const pair<string,string>& lhs, const pair<string,string>& rhs) {return lhs.first < rhs.first; });
    sort(p2.begin(), p2.end(), [](const pair<string,string>& lhs, const pair<string,string>& rhs) {return lhs.first < rhs.first; });
    //initialize vectors
    std::vector<pair<string,string>> v(p1.size() + p2.size());
    std::vector<pair<string,string>>::iterator it;
    //compute union
    it=std::set_union(p1.begin(), p1.end(),p2.begin(), p2.end(), v.begin());
    v.resize(it-v.begin());
    //print size
    //size = 4
    cout << v.size() << endl;
    return 0;
}

Solution

  • The union is done on the pairs, with the default operator<. ("A", "1") is different from ("A", "4").

    Give your comparator to std::set_union to achieve the expected result:

    it=std::set_union(p1.begin(), p1.end(),p2.begin(), p2.end(), v.begin(),
        [](const pair<string,string>& lhs, const pair<string,string>& rhs) { return lhs.first < rhs.first; });
    

    Notice 1:

    You should also name your lamda instead of typing it several times.

    And I would use v.reserve and back_inserter(v) instead allocating the vector and using v.begin() to collect output:

     (...)
        //save comparator
        auto comp = [](const pair<string,string>& lhs, const pair<string,string>& rhs) {return lhs.first < rhs.first; };
        //sort vectors according to first element
        sort(p1.begin(), p1.end(), comp);
        sort(p2.begin(), p2.end(), comp);
        //initialize vectors
        std::vector<pair<string,string>> v;
        v.reserve(p1.size() + p2.size());
        //compute union
        std::set_union(p1.begin(), p1.end(), p2.begin(), p2.end(), back_inserter(v), comp);
        //print size
        //size == 4
        cout << v.size() << endl;
    }
    

    Notice 2: what you do is similar to std::map