Let's say I have my data in a 4 by 3 vector<vector<int> > as:
1 2 3
4 5 6
7 8 9
10 11 12
and I want to delete every row containing the element 8 and end up like:
1 2 3
4 5 6
10 11 12
I have been trying to do:
for (vector<vector<int> >::iterator it = v.begin(); it != v.end(); it++) {
if (find(it->begin(), it->end(), 8)) {
// I will remove the row in here
}
}
which gives me:
error: no matching function for call to 'find(std::vector<int>::iterator, std::vector<int>::iterator, int)'
I don't have much experience with stl so I was wondering:
what's wrong with my find call?
is it safe to remove an element from a vector while iterating over it?
Ofc any elegant solution to my problem is also welcomed..
what's wrong with my find call?
You probably forgot to #include <algorithm>
is it safe to remove an element from a vector while iterating over it?
Look into the erase-remove idiom - erasing vector elements can be tricky.
Related
I have a sorted(according to first.second element)vector pair of following type :
vector<pair<pair<int,int>,int>>p;
My Comparator function to sort vector pair
bool sortbysec(pair<pair<int,int>,int>&a,pair<pair<int,int>,int>&b)
{
if(a.first.second==b.first.second)return a.first.first<b.first.first;
else return a.first.second<b.first.second;
}
I want upper bound of p.first.secondelement on the list of p.first.firstelements.
For example -
2 2 7
1 3 4
1 4 3
4 5 8
5 7 5
4 8 6
5 8 1
6 8 9
8 8 0
8 9 2
In simple words, I want an upper bound of middle element of the vector pair.Searching the upper bound of that particular element should be done in list of first element of the vector pair.
For Example, upper bound of 3 in second row is 4 in the 4th row.
My question is :
I dont know how to code this thing. I have tried this syntax(incorrect):
auto it=lower_bound(v.begin(),v.end(),make_pair(make_pair(2,2),7));
This is showing error.
I hope you understood the question.
Please anyone tell me a way how to code it properly so i get the desired results in c++ only.
Say, I have two vector as follows in the code, I want to erase the elements indexed by vector "index_to_filter" in the vector "data" using iterators. The dummy way in the code is just to point the obvious error. So far, I couldn't get it working, nor, figured out if this could be an erase-remove-idiom?. Is there a way to and am missing it ?
Thx.
#include <iostream>
#include <vector>
int main()
{
std::vector<int> data{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
std::vector<int> index_to_filter{ 1, 5, 8 };
/* needed result data = { 0, 2, 3, 4, 6, 7, 9 }*/
std::vector<int>::iterator iter = index_to_filter.begin();
while (iter != index_to_filter.end())
{
std::vector<int>::iterator iter_data = data.begin() + *iter;
iter_data = data.erase(iter_data);
iter++;
}
/* Throws : vector erase iterator outside range */
for (int i: data)
std::cout << i << std::endl;
system("pause");
return 0;
}
PS: the vector.erase question is aborded tens of times here but found no clue for this one !
PS: Solutions without iterators are not welcome. (No offense !)
thanks
Your problem is very simple:
std::vector<int> index_to_filter{ 1, 5, 8 };
You intent is to remove elements #1, #5, and #8 from the other array, and you start with element #1:
Value 0 1 2 3 4 5 6 7 8 9
Index 0 1 2 3 4 5 6 7 8 9
^ ^ ^
The bottom line, the "index" line, is the index into the vector. The top line, the "value" line, is the value in that position in the vector. When you start, the two values are the same.
The carets mark the indexes you wish to remove, and you start with element #1.
The fundamental gap that you are ignoring is that when you remove an element from the vector, you do not exactly have a gaping black hole, a void in that position. All subsequent values in the container shift over. So, when you remove element #1, the remaining values shift over:
Value 0 2 3 4 5 6 7 8 9
Index 0 1 2 3 4 5 6 7 8
^ ^
The next element you wish to remove is element #5. Unfortunately, the value at that position in the vector is no longer 5. It is 6, because the array has shifted. Your code than proceeds and removes index position #5, which has the following result:
Value 0 2 3 4 5 7 8 9
Index 0 1 2 3 4 5 6 7
^
You have already gone off the rails here. But now, your code attempts to remove index #8, which no longer exists, since the vector is now shorter. As soon as your code attempts to do that, you blow up.
So, in conclusion: what you're missing is the simple fact that removing a value from a middle of a vector shifts all subsequent values up by one position, in order to fill the gap left from the removed element, and the code you wrote fails to account for that.
The simplest solution is to remove elements from the highest index position to the lowest. In your code, you already have index_to_filter in sorted order, so instead of iterating from the beginning of index_to_filter to its end, from the lowest to the highest index, iterate backwards, from the last index in index_to_filter to the first, so your code attempts to remove indexes 8, 5, then 1, so that each time the removal of the element does not affect the lower index positions.
If index_to_filter is guaranteed to be sorted, you should be able to just remove the elements in reverse order - the index to filter is still correct as long as no previous entries have been removed.
So just call index_to_filter.rbegin() and index_to_filter.rend() in your current code.
This question already has answers here:
How can I shift elements inside STL container
(2 answers)
Closed 9 years ago.
For example, I have a vector, and I want to move the element at position 1 to a new position 3.
std::vector<int> v;
for (int i = 0; i < 5; ++i)
v.push_back(i);
// move element at position 1 to 3
// old vector: 0 1 2 3 4
// after move: 0 2 3 1 4
Use std::rotate
std::rotate( v.begin() + 1, v.begin() + 2, v.begin() + 4 );
// ^^^^^ 1 ^^^^^ 2 ^^^^^ 3
// 1 - beginning of the range to rotate - points to '1'
// 2 - element that will be brought to beginning after rotation - points to '2'
// 3 - one past end of range to rotate - points to '4'
Use the rotate algorithm. That will rotate the elements in a given range.
you can use std::swap two times.
std::swap(v[1], v[2]);
std::swap(v[2],v[3]);
Given
0 1 2 3 4
first swap:
0 2 1 3 4
second swap
0 2 3 1 4
you get what you want
If you specify a range [i,j], you can put these into a function and apply swap by looping through v[i] to v[j].
Following program is missing one permutation entry.
#include <iostream>
#include <vector>
#include <algorithm>
int main ( int argc, char **argv) {
std::vector<int> temp;
temp.push_back(10);
temp.push_back(2);
temp.push_back(4);
temp.push_back(4);
do {
std::copy(temp.begin(),temp.end(),std::ostream_iterator<int>(std::cout," "));
std::cout << std::endl;
}while ( std::next_permutation (temp.begin(), temp.end()));
}
Following is the output of the program
10 2 4 4
10 4 2 4
10 4 4 2
why it is missing one entry which is
2 4 4 10
This is because that permutation is the first ordering for the list of number that you have.
You would need to sort the original array, then this permutation will be listed as the very first one.
std::vector<int> temp;
temp.push_back(10);
temp.push_back(2);
temp.push_back(4);
temp.push_back(4);
std::sort(temp.begin(),temp.end() );
Alternatively, you could just push the elements in sorted order, but for practical purposes, you should always sort if you want to generate all possible permutations.
It's actually missing a few other valid permutations: 2 10 4 4 and 2 4 10 4, and 4 4 10 2 for example.
As to why they are missing: it says, right there in the documentation:
Return value
true if the function could rearrange the object as a lexicographically greater permutation. Otherwise, the function returns false to indicate that the arrangement is not greater than the previous, but the lowest possible (sorted in ascending order).
So the while loop ends after 10 4 4 2, because that is the lexicographically greatest permutation (the one that's "biggest" when you compare them left-to-right, i.e. the one that's in descending order). After printing that one, next_permutation fails to get to the 'next' permutation, and wraps around to the "beginning" permutation of 2 4 4 10; but that is not printed because the function also returned false.
dear all,
i have a map, defined as map<int, vector<int> > my_map. So, for example it looks like as follows,
my_map=
0 1 2 6 5 4
1 0 2 3 4 5
2 0 1 4
3 1
4 1 2 0 7 5 6
5 1 0 6 4
6 0 5 4
7 4
vector<int> element_common(map<int, vector<int> > &my_map, int s1, int s2){
vector<int> common2;
vector<int> first_vector=my_map[s1];
vector<int>::iterator snd_vector_begin= my_map[s2].begin();
vector<int>::iterator snd_vector_end= my_map[s2].end();
for (vector<int>::iterator any=first_vector.begin();
any!=first_vector.end();
any++){
// check if any is in other_list
vector<int>::iterator any_in_snd_vector_iterator= find (snd_vector_begin,snd_vector_end, *any);
if(any_in_snd_vector_iterator==snd_vector_end){
common2.push_back(*any);
}
}
return common2;
i wrote a function above function to get common elements from the vector parts which are relevant to 2 given keys. when keys are equal to s1 and s2, i.e. s1=1 and s2=4. then my function should give me 0,2,5. but i got 3,4. please help me to rectify my function.
If you can guarantee your vectors are sorted then you can improve your performance substantially from O(mn) to O(m + n):
std::vector<int> common;
std::set_intersection(vec1.begin(), vec1.end(),
vec2.begin(), vec2.end(),
std::back_inserter(common));
You got the test exactly backwards:
if(any_in_2nd_vector_iterator==2nd_vector_end){
is true when the element ISN'T FOUND in the second vector. Try !=.
Then, you can avoid needless copying of vectors by using a reference:
const vector<int>& first_vector=my_map[s1];
and if your vectors get much larger, it may be faster to do a hash lookup (or pre-sorted merge if the vectors are always kept sorted) instead of a call to find which has to check every element.