C++ Erase Vector Element by Value Rather Than by Position

C++ Erase vector element by value rather than by position?

How about std::remove() instead:

#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 8), vec.end());

This combination is also known as the erase-remove idiom.

Remove an element from a vector by value - C++

You could use the Erase-remove idiom for std::vector

Quote:

std::vector<int> v; 
// fill it up somehow
v.erase(std::remove(v.begin(), v.end(), 99), v.end());
// really remove all elements with value 99

Or, if you're sure, that it is unique, just iterate through the vector and erase the found element. Something like:

for( std::vector<T>::iterator iter = v.begin(); iter != v.end(); ++iter )
{
if( *iter == VALUE )
{
v.erase( iter );
break;
}
}

remove element by position in a vector string in c++

[Note: With the assumption 1003;2021-03-09;False;0;0;1678721F corresponding to a row inside std::vector<string>]


std::remove : Removes from the vector either a single element (position) or a range of elements ([first, last)).

In case std::vector<string> plan contains value False then it is removed.

  std::vector < std::string > plan =
{
"1003","2021-03-09","False","0;0","1678721F"

};

std::remove(plan.begin(),plan.end(),"False");

In your case you need to remove given sub-string from each row of the plan. You need to iterate through all the rows to remove given value using std::string::erase.

  std::vector < std::string > plan =
{
"1003;2021-03-09;False;0;0;1678721F",
"1005;2021-03-05;False;0;0;1592221D",
"1005;2021-03-06;False;0;0;1592221D",
"1003;2021-03-07;False;0;0;1592221D",
"1003;2021-03-08;False;0;0;1592221D",
"1004;2021-03-09;False;0;0;1592221D",
"1004;2021-03-10;False;0;0;1592221D",
"1001;2021-03-11;False;0;0;1592221D"};

for (auto & e:plan)
{
//As position of False;0;0; is at a fixed index, i.e: from index:16, 10 characters are removed
e.erase (16, 10);
}

To generalize, You can make use of std::String::find to find a sub-string and erase it.

void removeSubstrs(string& s, string p) { 
string::size_type n = p.length();
for (string::size_type i = s.find(p);
i != string::npos;
i = s.find(p))
s.erase(i, n);
}

int
main ()
{

std::vector < std::string > plan =
{
"1003;2021-03-09;False;0;0;1678721F",
"1005;2021-03-05;False;0;0;1592221D",
"1005;2021-03-06;False;0;0;1592221D",
"1003;2021-03-07;False;0;0;1592221D",
"1003;2021-03-08;False;0;0;1592221D",
"1004;2021-03-09;False;0;0;1592221D",
"1004;2021-03-10;False;0;0;1592221D",
"1001;2021-03-11;False;0;0;1592221D"};

for (auto & e:plan)
{
removeSubstrs (e, ";False;0;0");
}

for (auto e:plan)
std::cout << e << std::endl;


return 0;
}

How do I erase an element from std::vector by index?

To delete a single element, you could do:

std::vector<int> vec;

vec.push_back(6);
vec.push_back(-17);
vec.push_back(12);

// Deletes the second element (vec[1])
vec.erase(std::next(vec.begin()));

Or, to delete more than one element at once:

// Deletes the second through third elements (vec[1], vec[2])
vec.erase(std::next(vec.begin(), 1), std::next(vec.begin(), 3));

How do I remove an item from a stl vector with a certain value?

std::remove does not actually erase elements from the container: it moves the elements to be removed to the end of the container, and returns the new end iterator which can be passed to container_type::erase to do the actual removal of the extra elements that are now at the end of the container:

std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());

How to find a value to remove from a vector, and remove the same position from a secondary vector?

First of all, a vector called set1 or set2 is strange. Why not use std::set?

Anyway, supposing that set2 is not smaller than set1, a very generic solution would be to use std::distance to calculate the distance between the find result and the start of set1. You can then just add the distance to the start of set2:

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

int main()
{
std::vector<int> set1 = { 4, 5, 2 };
std::vector<std::string> set2 = { "a", "b", "c" };

using std::begin;
using std::end;

// get iterator to first '5' element:
auto const set1_iter = std::find(begin(set1), end(set1), 5);

// how many steps does it take to go from start to the '5' element?
auto const distance = std::distance(begin(set1), set1_iter);

// go to same position in set2:
auto const set2_iter = begin(set2) + distance;

// use position to erase the element:
set2.erase(set2_iter);

for (auto&& element : set2)
{
std::cout << element << "\n";
}
}

In real code, you will want to add some error handling for the case when set2 is smaller or when 5 does not exist.

std::vector removing elements which fulfill some conditions

std::remove_if comes to the rescue!

99 would be replaced by UnaryPredicate that would filter your delays, which I am going to use a lambda function for.

And here's the example:

v.erase(std::remove_if(
v.begin(), v.end(),
[](const int& x) {
return x > 10; // put your condition here
}), v.end());

vector erase specific indexes with iterators (not based on range or condition)

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.

How to remove element from vector by value but only single instance of that value?

You may use:

v.erase(v.begin() + std::max(index1, index2));
v.erase(v.begin() + std::min(index1, index2));

or even

auto indexes = std::minmax(index1, index2);
v.erase(v.begin() + indexes.second);
v.erase(v.begin() + indexes.first);

C++ Remove element from vector by value

std::remove is only available if you include header <algorithm>.

This is clearly stated by the MSDN documentation here as well as any C++ reference.



Related Topics



Leave a reply



Submit