Connecting Tech Pros Worldwide Help | Site Map

Removing elements from std::vector.

  #1  
Old July 22nd, 2005, 10:53 PM
Jason Heyes
Guest
 
Posts: n/a
What is a good way of removing elements from std::vector so that the
elements removed satisfy a predicate and end up stored in another
std::vector. It seems as though the algorithm std::remove_if only achieves
half the job. Here is how I would use std::remove_if to remove elements from
std::vector based on predicate:

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

After that line is executed I cannot get back the elements that were
removed. So I try to add something before the line:

using namespace std;
remove_copy_if(v.begin(), v.end(), back_inserter(r), not1(pred));
v.erase(remove_if(v.begin(), v.end(), pred), v.end());

This code does the job but it requires twice as many calls to the predicate.
Anyone care to show me an improvement on this? Thanks.


  #2  
Old July 22nd, 2005, 10:53 PM
Siemel Naran
Guest
 
Posts: n/a

re: Removing elements from std::vector.


"Jason Heyes" <jasonheyes@optusnet.com.au> wrote in message
news:41982632$0$27451
[color=blue]
> What is a good way of removing elements from std::vector so that the
> elements removed satisfy a predicate and end up stored in another
> std::vector. It seems as though the algorithm std::remove_if only achieves
> half the job. Here is how I would use std::remove_if to remove elements[/color]
from[color=blue]
> std::vector based on predicate:[/color]

How about:

typedef std::vector<Whatever>::iterator Iter;
Iter newend = std::remove_if(v.begin(), v.end(), pred);
r.reserve(v.end()-newend);
std::copy (newend, v.end(), back_inserter(r));
v.erase(newend, v.end());

Now you have N calls to pred.operator(), but 2M or more calls to the
operator= or copy constructor (where M is the number of elements to remove):
remove_if uses operator= to move the removed elements to the end of the
vector, and std::copy invokes M calls to the copy constructor. If your
class Whatever is small or a smart pointer class, then this should be OK.

There might be a special remove_if function in STL that moves the removed
elements to a new range, but I don't know that yet.


  #3  
Old July 22nd, 2005, 10:53 PM
David Harmon
Guest
 
Posts: n/a

re: Removing elements from std::vector.


On Mon, 15 Nov 2004 14:44:16 +1100 in comp.lang.c++, "Jason Heyes" <jasonheyes@optusnet.com.au> wrote,[color=blue]
>v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());
>
>After that line is executed I cannot get back the elements that were
>removed. So I try to add something before the line:[/color]

Save the iterator. Use it twice.

vector<value_type>::iterator it = remove_if(v.begin(), v.end(), pred);
copy(it, v.end(), back_inserter(r));
v.erase(it, v.end());


  #4  
Old July 22nd, 2005, 10:53 PM
Jason Heyes
Guest
 
Posts: n/a

re: Removing elements from std::vector.


"Siemel Naran" <SiemelNaran@REMOVE.att.net> wrote in message
news:CWYld.907619$Gx4.526580@bgtnsc04-news.ops.worldnet.att.net...[color=blue]
> "Jason Heyes" <jasonheyes@optusnet.com.au> wrote in message
> news:41982632$0$27451
>[color=green]
>> What is a good way of removing elements from std::vector so that the
>> elements removed satisfy a predicate and end up stored in another
>> std::vector. It seems as though the algorithm std::remove_if only
>> achieves
>> half the job. Here is how I would use std::remove_if to remove elements[/color]
> from[color=green]
>> std::vector based on predicate:[/color]
>
> How about:
>
> typedef std::vector<Whatever>::iterator Iter;
> Iter newend = std::remove_if(v.begin(), v.end(), pred);
> r.reserve(v.end()-newend);
> std::copy (newend, v.end(), back_inserter(r));
> v.erase(newend, v.end());
>
> Now you have N calls to pred.operator(), but 2M or more calls to the
> operator= or copy constructor (where M is the number of elements to
> remove):
> remove_if uses operator= to move the removed elements to the end of the
> vector, and std::copy invokes M calls to the copy constructor. If your
> class Whatever is small or a smart pointer class, then this should be OK.
>
> There might be a special remove_if function in STL that moves the removed
> elements to a new range, but I don't know that yet.
>[/color]

Your code copies the wrong elements into r. Better luck next time.


  #5  
Old July 22nd, 2005, 10:53 PM
Jason Heyes
Guest
 
Posts: n/a

re: Removing elements from std::vector.


"David Harmon" <source@netcom.com> wrote in message
news:42386224.769913031@news.west.earthlink.net...[color=blue]
> On Mon, 15 Nov 2004 14:44:16 +1100 in comp.lang.c++, "Jason Heyes"
> <jasonheyes@optusnet.com.au> wrote,[color=green]
>>v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());
>>
>>After that line is executed I cannot get back the elements that were
>>removed. So I try to add something before the line:[/color]
>
> Save the iterator. Use it twice.
>
> vector<value_type>::iterator it = remove_if(v.begin(), v.end(), pred);
> copy(it, v.end(), back_inserter(r));
> v.erase(it, v.end());
>[/color]

Your code copies the wrong elements into r. Care to try again?


  #6  
Old July 22nd, 2005, 10:54 PM
Howard Hinnant
Guest
 
Posts: n/a

re: Removing elements from std::vector.


In article <41982632$0$27451$afc38c87@news.optusnet.com.au> ,
"Jason Heyes" <jasonheyes@optusnet.com.au> wrote:
[color=blue]
> What is a good way of removing elements from std::vector so that the
> elements removed satisfy a predicate and end up stored in another
> std::vector. It seems as though the algorithm std::remove_if only achieves
> half the job. Here is how I would use std::remove_if to remove elements from
> std::vector based on predicate:
>
> v.erase(std::remove_if(v.begin(), v.end(), pred), v.end());
>
> After that line is executed I cannot get back the elements that were
> removed. So I try to add something before the line:
>
> using namespace std;
> remove_copy_if(v.begin(), v.end(), back_inserter(r), not1(pred));
> v.erase(remove_if(v.begin(), v.end(), pred), v.end());
>
> This code does the job but it requires twice as many calls to the predicate.
> Anyone care to show me an improvement on this? Thanks.[/color]

Consider partition:

i = partition(v.begin(), v.end(), pred);

And then do whatever you want with your two sets: [v.begin(), i) and
[i, v.end()). The first set is the one with pred true.

-Howard
  #7  
Old July 22nd, 2005, 10:55 PM
Jason Heyes
Guest
 
Posts: n/a

re: Removing elements from std::vector.


"Howard Hinnant" <hinnant@metrowerks.com> wrote in message
news:hinnant-556089.09190115112004@syrcnyrdrs-02-ge0.nyroc.rr.com...[color=blue]
> Consider partition:
>
> i = partition(v.begin(), v.end(), pred);
>
> And then do whatever you want with your two sets: [v.begin(), i) and
> [i, v.end()). The first set is the one with pred true.
>
> -Howard[/color]

Thanks heaps for this. It solves other problems I've been having.


Closed Thread


Similar Threads
Thread Thread Starter Forum Replies Last Post
removing elements from vector<int> using <algorithm> arnuld answers 10 October 10th, 2007 09:15 PM
Removing elements from vector kaferro@hotmail.com answers 11 November 24th, 2006 02:45 AM
adding/removing elements from std::vector Tino answers 1 July 22nd, 2005 07:45 AM