Reputation: 2722
I am trying to delete an element in a vector of Objects. The vector is filled with instances of Object
and at some point, I want to remove a certain element in a vector not by index, but by the element itself.
A simple example would be:
std::vector< string > strVector;
strVector.push_back( "abc" );
strVector.push_back( "def" );
strVector.push_back( "ghi" ); // So strVector should contain "abc", "def", and "ghi"
How do I remove "ghi" from that vector? Note that I don't know where "ghi" is in that vector.
// Something like this. Assume strVector = [ "abc", "cba", "ccb", "bac", "aaa" ]
strVector.removeElement( "ccb" );
A more relevant example to what I a working on:
class MyClass {
std::vector< Object > myObjVector;
void main( ARGS ) {
for ( int i = 0; i < 10; i++ ) {
Object myObject = Object( );
myObjVector.push_back( myObject );
}
int j = getANumber( ); // j could be any number within the size of the vector
Object myOtherObject = myObjectVector.at( j );
// How do I erase myOtherObject (which is an object inside the vector) ?
removeFromVector( myOtherObject );
}
}
I hope the question's clear. Thanks in advance.
EDIT: I figured it out, thanks to all those who answered. The trick was to give the class something unique that identifies it (like a name or a tag, as long as they are guaranteed to be unique) then use the erase-remove idiom to remove the object from the array.
Upvotes: 1
Views: 558
Reputation: 227418
If your use-case has no duplicates, then you are better off using an std::set
and using the std::set::erase which takes a value.
std::set< string > strSet;
strSet.insert( "abc" );
strSet.insert( "def" );
strSet.insert( "ghi" );
strSet.insert( "ccb" );
strSet.erase("ccb");
If you need to cope with duplicates, then you have to specify the desired behaviour of the removal. Should it remove one or all of the elements matching a value? Do you care about preserving the order of the remaining elements? If you require using a vector, then lokk at the erase-remove idiom. But note that std::vector::erase
has linear time complexity, whereas the relevant variant of std::set::erase
has logarithmic time complexity. And erase-remove would remove all elements equal to the given value.
Note: if you want to use an std::set
for a user defined type, you must provide either a less-than bool operator<(const UserType&) const
or a comparison function or functor, implementing strict weak ordering.
Upvotes: 6
Reputation: 153919
If the objects in the vector support equality, and that's the condition for removal, then you can use:
v.erase( std::remove( v.begin(), v.end(), "ghi" ), v.end() );
Otherwise, you'll need remove_if
, with a functional object (or lambda,
if you have C++11) which returns true if the element is to be removed.
Upvotes: 1
Reputation: 2406
#include <iostream>
#include <vector>
class Object
{
public:
Object(int n){secret_num = n;}
virtual ~Object(){}
int getSecretNum(){return secret_num;}
private:
int secret_num;
};
int main()
{
int index= -1;
Object *urobj = new Object(104);
std::vector<Object*> urvector;
for(int i = 0; i < 10; ++i)
{
Object *obj = new Object(i+1);
urvector.push_back(obj);
}
urvector.push_back(urobj);
for(int j = 0; j < urvector.size(); ++j)
{
Object *tmp = urvector.at(j);
std::cout << tmp->getSecretNum() << std::endl;
if(urobj == tmp)
index = j;
}
if(index == -1)
std::cout << " not match " << std::endl;
else
std::cout << " match " << index << std::endl;
return 0;
}
Upvotes: 0
Reputation: 121971
If you must use a vector
, then use erase(remove())
:
#include <algorithm>
#include <string>
#include <vector>
strVector.erase(std::remove(strVector.begin(), strVector.end(), "ghi"),
strVector.end());
this will remove all instances of "ghi"
from strVector
.
Upvotes: 4