Extract element from 2 vectors? - c++

I have 2 vector of with one has vec1{e1,e2,e3,e4} and the other one with vec2 {e2,e4,e5,e7}
How to effectively get three vector from above vectors such that 1.has elements that is available only in vec1 similarly 2 has only vec2 elements and 3.with common elements

std::set_intersection should do the trick, if both vectors are sorted:
http://msdn.microsoft.com/en-us/library/zfd331yx.aspx
std::set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), std::back_inserter(vec3));
A custom predicate can be used for the comparison too:
std::set_intersection(vec1.begin(), vec1.end(), vec2.begin(), vec2.end(), std::back_inserter(vec3), my_equal_functor());
If they are not sorted, you may of course sort them first, or alternatively, you can iterate through vec1, and for each element, use std::find to see if it exists in vec2.

What you're asking for is that vec3 be the intersection of the other two. Jalf demonstrates how to populate vec3 using the std::set_intersection function from the <algorithm> header. But remember that for the set functions to work, the vectors must be sorted.
Then you want vec1 and vec2 to be the difference between themselves and vec3. In set notation:
vec1 := vec1 \ vec3;
vec2 := vec2 \ vec3;
You can use the std::set_difference function for that, but you can't use it to modify the vectors in-place. You'd have to compute another vector to hold the difference:
std::vector<foo> temp;
std::set_difference(vec1.begin(), vec1.end(),
vec3.begin(), vec3.end(),
std::back_inserter(temp));
vec1 = temp;
temp.clear();
std::set_difference(vec2.begin(), vec2.end(),
vec3.begin(), vec3.end(),
std::back_inserter(temp));
vec2 = temp;

If the element count is low, you can use the naive approach which is easy to implement and has O(n2) running time.
If you have a large number of elements, you can build a hash table from one of them and look up other vector's elements in it. Alternatively, you could sort one of them and binary search through it.

The problem you describe is vector intersection. This depends on the size of the input vectors.
If the sizes of both vectors are close to each other a merge (like in merge-sort) is best. If one vector is much smaller than the other do the following: For each element of the smaller vector search for that element in the larger vector using binary search.
This is a common problem in information retrieval, where you have to intersect inverted indices. There are some research papers on this.

Related

How to remove duplicates from a vector whose numbers might be in different positions?

How do you remove elements from a vector of vectors that are identical to another vector but whose elements are not in the same indices?
For example:
std::vector<vector<int>> vectA = {{1,3,4}. {1,2,3}, {3,2,1};
I want it so that {3,2,1} is removed from vectA and it becomes:
vectA = {{1,3,4}, {1,2,3}}
Any idea how to proceed efficiently?
Sort the elements of each vector
Drop duplicates (this is an easy look-up)
If you need to retain the original element order, then build any correspondence you wish: parallel arrays of vectors (original and sorted), pairs of (unsorted, sorted) vectors, etc. Drop duplicates based on the sorted ones.
I trust that you can take it from here.
What you are describing is the behavior of std::set, ie. this solves your problem:
set<set<int>> input = {{1,3,4}, {1,2,3}, {3,2,1}};
// input is now {{1,2,3},{1,3,4}}
This works because a set is basically equal to a sorted vector with no duplicates.
If you really want to, you can now convert to std::vector:
vector<vector<int>> nums;
for(auto & s : input) nums.emplace_back(s.begin(), s.end());

C++: Efficient way to check if elements in a vector are greater than elements in another having same indices?

I have a vector < vector <int> > like so:
v = {{1,2,3}, {4,2,1}, {3,1,1}....}}
All v's elements like v[0], v[1], v[2]... have the same size. There may be duplicate elements.
What I am trying to do is to find and delete vectors (like v[2]) that are "majorized" by another vector (like v[1]), i.e. all elements of v[1] are greater than/equal to the respective elements(in order of indices) in v[2].
A naive way of doing this would be to loop thorough v and compare each vector with another vector and further compare each element with another vector's element.
But I feel there must a better way to do this without getting O(n^3) in the number of elements of all the vectors in v.
If multiple vectors are equal, I need only one of them (i.e delete all except one). A random choice would be sufficient.
Any thoughts or ideas are appreciated!
This is called the maxima of a point set. For two and three dimensions, this can be solved in O(n log n) time. For more than three dimensions, this can be solved in O(n(log n)^(d − 3)  log log n) time. For random points, a linear expected time algorithm is available.

Fastest way to check if element is in both vectors

So, think that we have two vectors, vec1 and vec2. What would be the fastest way to only perform some operation to elements, which are in both vectors.
This far, I have made this. Simply, how can we achieve this faster, or is there any way:
vector<Test*> vec1;
vector<Test*> vec2;
//Fill both of the vectors, with vec1 containing all existing
//objects of Test, and vec2 containing some of them.
for (Test* test : vec1){
//Check if test is in vec2
if (std::find(vec2.begin(), vec2.end(), test) != vec2.end){
//Do some stuff
}
}
Your approach is O(M*N) because it calls std::find linear in the number of elements of vec2 for each element of vec1. You can improve upon it in several ways:
Sorting vec2 would let you reduce the time to O((N+M)*Log M) - i.e. you can use binary search on the range vec2.begin(), vec2.end()
Sorting both vectors would let you search in O(NLog N + MLog M) - you could use an algorithm similar to merging sorted ranges to find matching pairs in linear time
Using a hash set for vec2 element would let you reduce the time to O(N+M) - now both the construction time of the set and the search in it are linear.
One easy way is to std::unordered_set
vector<Test*> vec1;
vector<Test*> vec2;
//Fill both of the vectors, with vec1 containing all existing
//objects of Test, and vec2 containing some of them.
std::unordered_set<Test*> set2(vec2.begin(),vec2.end());
for (Test* t : vec1) {
//O(1) lookup in hash set
if (set2.find(t)!=set2.end()) {
//stuff
}
}
O(n+m), where n is the number of elements in vec1, m is the number of elements in vec2
}

how to concatenate Vectors in Eigen?

I have two vectorXd in my program and I like to concatenate them into one vector, so that the second one's values goes after the first one, I found this for matrix but it doesn't seem to work on Vectors:
Eigen how to concatenate matrix along a specific dimension?
Like so, assuming you have vec1 and vec2 already:
VectorXd vec_joined(vec1.size() + vec2.size());
vec_joined << vec1, vec2;
(Note that the vector types are simply typedefs of matrix types constrained to have only one column.)
Further reading: Advanced initialization

The best practice solution of differenses search of two STL vectors

I have already two STL vectors. For instance:
vector<int> MyList;
MyList.push_back(10);
MyList.push_back(20);
MyList.push_back(30);
MyList.push_back(40);
MyList.push_back(50);
vector<int> MyListSub;
MyListSub.push_back(20);
MyListSub.push_back(30);
MyListSub.push_back(40);
And I want to get the number of elements which is in the MyListSub and isn't in MyList.
For this instance, result is "2"
You can use std::set_difference for this:
std::vector<int> diff;
std::set_difference(MyList.begin(), MyList.end(),
MyListSub.begin(), MyListSub.end(),
std::back_inserter(diff));
As #Jan points out, the vectors have to be sorted. If they are not, use std::sort to sort them:
std::sort(MyList.begin(), MyList.end());
Alternatively you can consider storing your elements in an std::set in the first place, thus they will already be sorted.