Remove an element from a vector by value - C++ [duplicate]
Asked Answered
C

4

22

If I have

vector<T> list

Where each element in the list is unique, what's the easiest way of deleting an element provided that I don't know if it's in the list or not? I don't know the index of the element and I don't care if it's not on the list.

Countertype answered 3/10, 2011 at 7:10 Comment(5)
Why the name of a vector container is list .. It could be confusing, a lot (for someone, that reads your code)Lely
@KirilKirov, I don't think list is a reserved keyword in C++? Even so, it's just an example.Countertype
It is a container type, just as vector is. And both are pretty different :)Lely
is this a homework question or are you trying to solve a specific problem? if the latter describing the problem may give you alternative solutions, if the former you should tag it as homeworkClytemnestra
If all elements in your container must be unique and you don't need to use its index, you probably should use std::set<T> instead of vector.Citrange
L
33

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;
    }
}
Lely answered 3/10, 2011 at 7:14 Comment(4)
I would note that you can use find_if() instead of straight iterations.Citrange
Your 2nd answer .. I wouldn't do it this way. To extend to delete ALL occurrences of VALUE would trip people up in 2 possible places: iter is invalidated after .erase(), and ++iter would fail immediately. Would have to write iter=v.erase(iter); instead. Now if you do it that way, an extra ++iter will be committed after an erasure, skipping elements. To fix this you should always iterate backwards through the vector when deleting elements. Using a numerical index will fix these problems. for( int i = v.size()-1; i >= 0; i-- ) if( v[i]==VALUE ) v.erase( v.begin()+i ) ;Fourhanded
I know, but I said "to extend to delete"Fourhanded
@Fourhanded - true, but this is another answer, does not make my answer wrong.Lely
S
3

Based on Kiril's answer, you can use this function in your code :

template<typename T>
inline void remove(vector<T> & v, const T & item)
{
    v.erase(std::remove(v.begin(), v.end(), item), v.end());
}

And use it like this

remove(myVector, anItem);
Sukkah answered 23/4, 2014 at 11:28 Comment(0)
M
3

If occurrences are unique, then you should be using std::set<T>, not std::vector<T>.

This has the added benefit of an erase member function, which does what you want.

See how using the correct container for the job provides you with more expressive tools?

#include <set>
#include <iostream>

int main()
{
   std::set<int> notAList{1,2,3,4,5};

   for (auto el : notAList)
      std::cout << el << ' ';
   std::cout << '\n';

   notAList.erase(4);

   for (auto el : notAList)
      std::cout << el << ' ';
   std::cout << '\n';
}

// 1 2 3 4 5
// 1 2 3 5

Live demo

Magus answered 23/4, 2014 at 12:4 Comment(1)
A vector is used for a reason, e.g. preserving the insert order. so If occurrences are unique, then you should be using std::set<T>, not std::vector<T> is nowhere valid. Let's just focus on the OP's settings.Demon
O
1

From c++20

//LIKE YOU MENTIONED EACH ELEMENT IS UNIQUE
std::vector<int> v = { 2,4,6,8,10 };

//C++20 UNIFORM ERASE FUNCTION (REMOVE_ERASE IDIOM IN ONE FUNCTION)
std::erase(v, 8); //REMOVES 8 FROM VECTOR

Now try

std::erase(v, 12);

Nothing will happen, the vector remains intact.

Odd answered 14/7, 2022 at 20:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.