473,382 Members | 1,332 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

proper way to delete elements from a vector

I want to iterate through a vector and erase elements that meet a
certain criteria. I know there is an algorithmic way of doing this,
but first I would like to know how to do it with normal iteration. I'm
am trying to do something like:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

for (vector<int>::iterator iter = v.begin();
iter != v.end();
++iter)
{
if (*iter > 2) iter = v.erase(iter);
}
This is giving me an error saying: error: void value not ignored as it
ought to be. I'm sure what I'm doing is wrong, but I can't find a good
example of the right way to do this.

Thanks,
Carl

Nov 3 '05 #1
14 18556
have a look at this line........
iter = v.erase(iter);
can you see anything wrong with it?

G

Nov 3 '05 #2
On 2005-11-03 06:09:32 -0500, "Gr*****@nospam.com"
<Gr**********@gmail.com> said:
have a look at this line........

iter = v.erase(iter);

can you see anything wrong with it?


No, what do you think is wrong with it?

--
Clark S. Cox, III
cl*******@gmail.com

Nov 3 '05 #3

cayblood skrev:
I want to iterate through a vector and erase elements that meet a
certain criteria. I know there is an algorithmic way of doing this,
but first I would like to know how to do it with normal iteration. I'm
am trying to do something like:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

for (vector<int>::iterator iter = v.begin();
iter != v.end();
++iter)
{
if (*iter > 2) iter = v.erase(iter);
}
This is giving me an error saying: error: void value not ignored as it
ought to be. I'm sure what I'm doing is wrong, but I can't find a good
example of the right way to do this
Use the standard library for this:

std::erase(std::remove_if(v.begin(),v.end(),pred), v.end());

where pred is the predicate (designating the elements you want to
erase).
If you use boost::lambda, pred is as simple as _1 > 2. Otherwise you'll
have to use bind and std::greater (if i remember correctly) or write
your own predicate:

struct predicate
{
predicate(int val): val_(val) {}
bool operator<(int i) { return i > val_; }
private:
int val_;
};

and call it like this:
std::erase(std::remove_if(v.begin(),v.end(),predic ate(2)),v.end());

In real code, predicate should be renamed to e.g. less_than.
Perhaps there is already some std support for this.

/Peter
Thanks,
Carl


Nov 3 '05 #4
> This is giving me an error saying: error: void value not ignored as it
ought to be. I'm sure what I'm doing is wrong, but I can't find a good
example of the right way to do this.


Which compiler are you using? I do not see any technical errors in your
code.

--

Valentin Samko - http://www.valentinsamko.com

Nov 3 '05 #5

cayblood wrote:
I want to iterate through a vector and erase elements that meet a
certain criteria. I know there is an algorithmic way of doing this,
but first I would like to know how to do it with normal iteration. I'm
am trying to do something like:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

for (vector<int>::iterator iter = v.begin();
iter != v.end();
++iter)
{
if (*iter > 2) iter = v.erase(iter);
}


You forgot to qualify vector with std. vector exists in the standard
namespace. The following code was compiled with VC7.1. It is almost
exactly yours, apart from me qualifying vector with std. Note also the
algorthmic way. Your way was commented out, but does the same thing -
BTW, you had an error in your code. When an item is erased, the
following item remained because you should conditionally increment...

Here goes:

// CompileTest.cpp : Defines the entry point for the console
application.
//
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

template<class T>
struct print
{
void operator()( const T& t )
{
std::cout << t << std::endl;
}
};

int main(int argc, char* argv[])
{
typedef std::vector<int> ivect;
ivect v;

v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
//for( ivect::iterator iter = v.begin(); iter != v.end(); )
//{
// if (*iter > 2) iter = v.erase(iter);
// else ++iter;
//}
v.erase( std::remove_if( v.begin(), v.end(), std::bind2nd(
std::greater<int>(), 2 ) ), v.end() );

std::for_each( v.begin(), v.end(), print<int>() );

return 0;
}

Regards,

Werner

Nov 3 '05 #6

Gr*****@nospam.com wrote:
have a look at this line........
iter = v.erase(iter);
can you see anything wrong with it?
Hmmm, me neither.

G


Nov 3 '05 #7
v.erase( std::remove_if( v.begin(), v.end(), std::bind2nd(
std::greater<int>(), 2 ) ), v.end() );

std::for_each( v.begin(), v.end(), print<int>() );


The for_each could be replaced by:

std::copy( v.begin(), v.end(), std::ostream_iterator<int>(std::cout) );

The only difference is that this streams the data to std output
sequentially without cr/linefeed.

Regards,

W

Nov 3 '05 #8
apologies.... should have checked the return value from erase. My
mistake. It would have been a runtime error not acompile error in any
case G

Nov 3 '05 #9
On 2005-11-03, cayblood <ca*************@gmail.com> wrote:
I want to iterate through a vector and erase elements that meet
a certain criteria. I know there is an algorithmic way of
doing this, but first I would like to know how to do it with
normal iteration. I'm am trying to do something like:

vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);

for (vector<int>::iterator iter = v.begin();
iter != v.end();
++iter)
{
if (*iter > 2) iter = v.erase(iter);
}
vector<T>::erase returns an interator to the next element in the
vector, so in that case you mustn't increment iter.
This is giving me an error saying: error: void value not
ignored as it ought to be.


The code you posted doesn't seem to have that error. Post actual
code whenever possible. If it's an except, make it a complete and
compilable excerpt.

Here's one example of using erase in a loop:

for (vector<int>::iterator i = v.begin(); i != v.end(); /* */)
{
if (*i > 2) {
i = v.erase(i);
} else {
++i;
}
}

Using the standard functions remove_if and erase (as shown in
another post) will be better in most cases.

Note that remove_if does not actually erase elements. It swaps
elements that must be retained to the front of the container and
returns an iterator to the end of the swapped elements. So it's
usually combined with erase.

Assuming v is (1, 2, 3, 4), as above:

vector<int>::iterator i = remove_if(v.begin(), v.end(),
bind2nd(greater<int>(), 2));

If the standard functions objects are a mystery, you may define a
function instead.

bool greater_than_2(int i)
{
return i > 2;
}

vector<int>::iterator i = remove_if(v.begin(), v.end(), greater_than_2);

After either of those remove_if calls, v contains (1, 2, 3, 4).

Since the retained alements were already in front, nothing
happened. However, i now points to 3, and you can erase from
there to v.end() to get your final answer.

v.erase(i, v.end());

As shown in another poset, a popular idiom is to combine the
calls into one line, eliminating the temporary iterator.

v.erase(remove_if(v.begin(), v.end(), bind2nd(greater<int>(), 2))
, v.end());

--
Neil Cerutti
Nov 3 '05 #10
By "technical", I meant "compile time" errors here. You have a logical
problem, where you move to the next element calling iter = erase(iter)
(iter may be .end() at this point), and then you increment your
iterator, which leads to UB if iter was already pointing to the end.
Even if this doesn't happen, you will skip elements by effectively
incrementing your iterator twice (when you erase).

--

Valentin Samko - http://www.valentinsamko.com

Nov 3 '05 #11
By "technical", I meant "compile time" errors here. You have a logical
problem, where you move to the next element calling iter = erase(iter)
(iter may be .end() at this point), and then you increment your
iterator, which leads to UB if iter was already pointing to the end.
Even if this doesn't happen, you will skip elements by effectively
incrementing your iterator twice (when you erase).

--

Valentin Samko - http://www.valentinsamko.com

Nov 3 '05 #12
I need a slightly more complicated predicate and I'm having a hard time
creating it. I have a map that looks like this

map<Event, double> // Event is a user-defined class

I want to remove all elements of this map where
event.node_has_state(name, state). In other words, I need to call a
method on the first part of the pair and pass it two arguments.

I tried creating the following:

// predicate classes and functions for three argument predicates
template <class Arg, class Arg2, class Arg3, class Res> struct
ternary_function
{
typedef Arg argument_type;
typedef Arg2 argument_type;
typedef Arg3 argument_type;
typedef Res result_type;
};

// predicate for testing whether a node is in a certain state
template <class Elem, class NodeName, class StateName> struct
node_has_state :
public ternary_function<Elem, NodeName, StateName, bool>
{
bool operator()(const Elem& e, const NodeName& n, const StateName& s)
const
{
return e.node_has_state(n, s);
}
};

But I think that these work with vectors but not maps. Any
suggestions?

Thanks,

Carl

Original msg:
---------------------------------------
Peter Koch wrote:
Use the standard library for this:
std::erase(std::remove_if(v.begin(),v.end(),pred), v.end());

where pred is the predicate (designating the elements you want to
erase).
If you use boost::lambda, pred is as simple as _1 > 2. Otherwise you'll

have to use bind and std::greater (if i remember correctly) or write
your own predicate:

struct predicate
{
predicate(int val): val_(val) {}
bool operator<(int i) { return i > val_; }
private:
int val_;

};

and call it like this:
std::erase(std::remove_if(v.begin(),v.end(),predic ate(2)),v.end());

Nov 4 '05 #13

Neil Cerutti wrote:
On 2005-11-03, cayblood <ca*************@gmail.com> wrote: As shown in another poset, a popular idiom is to combine the
calls into one line, eliminating the temporary iterator.

v.erase(remove_if(v.begin(), v.end(), bind2nd(greater<int>(), 2))
, v.end());
Yes, I could/should have explained it better. Thanks,

W
--
Neil Cerutti


Nov 4 '05 #14
On 2005-11-04, cayblood <ca*************@gmail.com> wrote:
I need a slightly more complicated predicate and I'm having a
hard time creating it. I have a map that looks like this

map<Event, double> // Event is a user-defined class

I want to remove all elements of this map where
event.node_has_state(name, state). In other words, I need to
call a method on the first part of the pair and pass it two
arguments.


You cannot use remove_if on a map, since the key elements are
stored as const objects.

Use the map member functions find and erase, instead.

--
Neil Cerutti
Nov 4 '05 #15

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Martin Magnusson | last post by:
I'm getting segmentation faults when trying to fix a memory leak in my program. The problem is related to lists of pointers which get passed around between objects. Here is a description of how...
11
by: DamonChong | last post by:
Hi, I am new to c++. I recently spend an enormous among of time troubleshooting a seeminly innocuous piece of code. Although I narrow down this piece of code as the culprit but I don't...
9
by: david wolf | last post by:
I want to delete all even numbers in a vector, I am not sure if there's any better way to do it. Following program is how I did it. Look at the part of code beginning from comments: //delete all...
35
by: Jon Slaughter | last post by:
I'm having a problem allocating some elements of a vector then deleting them. Basicaly I have something like this: class base { private: std::vector<object> V;
10
by: Whybother | last post by:
I have this typedef map<__int64, int> Results_Map; __int64 is defined as 8 bytes ranging from -9,223,372,036.854,775,808 to 9,223,372,036.854,775,807 I have loaded it with approx 34 million...
7
by: JH Programmer | last post by:
Hi, is there any ways that allow us to delete an element in between? say int_val: 1 int_val: 2 int_val: 3
5
by: streamkid | last post by:
i have a class table, which has a vector of records(-db). i 'm trying to remove an element, but it doesn't seem to work.. i read this http://www.cppreference.com/cppvector/erase.html] and that's...
12
by: subramanian100in | last post by:
Suppose class Base { public: virtual ~Test() { ... } // ... }; class Derived : public Base
19
by: Daniel Pitts | last post by:
I have std::vector<Base *bases; I'd like to do something like: std::for_each(bases.begin(), bases.end(), operator delete); Is it possible without writing an adapter? Is there a better way? Is...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.