2

I have few vector. for eg 4

std::vector1 <CMyClass>;
std::vector2 <CMyClass>;
std::vector3 <CMyClass>;
std::vector4 <CMyClass>;

I want a resultant vector which will have the object which is present in all the vector. For eg. if

Vector1 has C1, C2, C3;
Vector2 has C1, C2;
Vector3 has C1, C4;
Vector has  C1, C5;

I want resultant vector to have C1.

I can run loop and compare and find out the resultant vector, but I would like to know if there is any direct way of doing it. Like some operator or data structure.

gsamaras
  • 71,951
  • 46
  • 188
  • 305
Geek
  • 273
  • 5
  • 19
  • 5
    Perhaps look into [`std::set_intersection`](http://en.cppreference.com/w/cpp/algorithm/set_intersection) – bgfvdu3w Oct 13 '17 at 16:13
  • Since you have more than two, [this](https://stackoverflow.com/questions/12875993/efficient-set-intersection-of-a-collection-of-sets-in-c) is probably more relevant. – bgfvdu3w Oct 13 '17 at 16:22

3 Answers3

2
  1. Sort the vectors.
  2. Use std::set_intersection() three times (as many vectors you have - 1).

Time Complexity Analysis:

  • 4 * O(nlogn) = O(nlogn)
  • linear in 2 * (firstSize + secondSize) - 1
  • linear in 2 * (firstSecondInterSize + thirdSize) - 1
  • linear in 2 * (firstSecondThirdInterSize + fourthSize) - 1

which is bounded by O(nlogn), meaning that sorting is the bottleneck of the algorithm.


Full code example:

#include <iostream>     // std::cout
#include <algorithm>    // std::set_intersection, std::sort
#include <vector>       // std::vector

int main () {
  std::vector<int> first = {5,10,15,20,25};
  std::vector<int> second = {50,40,30,20,10};
  std::vector<int> third = {10,20,3,4,0};
  std::vector<int> fourth = {4,20,10,3,6};
  std::vector<int> v(first.size() + second.size() + third.size() + fourth.size());
  std::vector<int>::iterator it;

  std::sort (first.begin(),first.end());
  std::sort (second.begin(),second.end());
  std::sort (third.begin(),third.end());
  std::sort (fourth.begin(),fourth.end());

  it=std::set_intersection (first.begin(), first.end(), second.begin(), second.end(), v.begin());
  it=std::set_intersection (v.begin(), v.end(), third.begin(), third.end(), v.begin());
  it=std::set_intersection (v.begin(), v.end(), fourth.begin(), fourth.end(), v.begin());
  v.resize(it-v.begin());

  std::cout << "The intersection has " << (v.size()) << " elements: ";
  for (it=v.begin(); it!=v.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

Output:

The intersection has 2 elements: 10 20

Ajay
  • 18,086
  • 12
  • 59
  • 105
gsamaras
  • 71,951
  • 46
  • 188
  • 305
0

That's an intersection, not a superset (that would mean the union, or collection of all the elements contained in any of the four vectors).

If you can sort the vectors, the direct way is to use std::set_intersection.

You'll have to use it three times, getting intermediate results A=intersection(v1,v2) and B=intersection(3,4) before getting the final result from intersection(A,B).

Using this linked answer will be more efficient (skipping the two intermediate containers), but does require more manual coding (and testing).

Useless
  • 64,155
  • 6
  • 88
  • 132
0

What about this? You have to add operator<() in your class (and auxiliary operator<<()). Form std::set from each vector, then calculate intersection of these sets. Again - make vector from resulting set.

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

class CMyClass
 {
 public:
     CMyClass(int n){_n=n;}
     ~CMyClass(){}
     bool operator<(const CMyClass a) const{return _n <a._n;}
     friend std::ostream& operator<<(std::ostream& s,const CMyClass& a){s<<a._n;return s;}
 private:
     int _n;
 };
vector<CMyClass> find_intersect(vector<vector<CMyClass>>& vecs)
{
    vector<CMyClass> res;
    if (vecs.empty()) return res;
    set<CMyClass> S;
    for_each(vecs[0].begin(),vecs[0].end(),[&S](const CMyClass& e){S.insert(e);});
    for(auto &vec:vecs)
    {
        set<CMyClass> s,tmp;
        for_each(vec.begin(),vec.end(),[&s](const CMyClass& e){s.insert(e);});
        set_intersection(S.begin(),S.end(),s.begin(),s.end(),std::inserter(tmp,tmp.begin()));
        S=tmp;
        if (S.empty()) break;
    }
    for_each(S.begin(),S.end(),[&res](const CMyClass& e){res.push_back(e);});
    return res;
}

int main()
{
    vector<CMyClass> v1={1,2,3};
    vector<CMyClass> v2={1,2};
    vector<CMyClass> v3={1,4};
    vector<CMyClass> v4={1,5};
    vector<vector<CMyClass>> vectors;
    vectors.push_back(v1);
    vectors.push_back(v2);
    vectors.push_back(v3);
    vectors.push_back(v4);
    auto res = find_intersect(vectors);
    cout<<"[";
    for(auto &elem:res)
        cout<<elem<<",";
    cout<<"]"<<endl;
}

Output: [1,]