Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > std::list remove element mid iteration

Reply
Thread Tools

std::list remove element mid iteration

 
 
Christopher
Guest
Posts: n/a
 
      12-20-2007
The situation is that a std::list<std::set<std::string> > is being
iterated through. Upon certain criteria some sets become empty. I need
to remove the empty sets from the list.

Is it safe to iterate through a list and call list::erase( iterator )
in mid iteration?
 
Reply With Quote
 
 
 
 
red floyd
Guest
Posts: n/a
 
      12-20-2007
Christopher wrote:
> The situation is that a std::list<std::set<std::string> > is being
> iterated through. Upon certain criteria some sets become empty. I need
> to remove the empty sets from the list.
>
> Is it safe to iterate through a list and call list::erase( iterator )
> in mid iteration?


Well, you can use

struct set_is_empty
{
bool operator()(const std::set& s) const { return s.empty(); }
};

std::erase(std::remove_if(l.begin(), l.end(), set_is_empty());

or else, the canonical iteration for this list is:

for (it = l.begin(); it != l.end(); )
if (it->empty())
it = l.erase(it);
else
++it;
 
Reply With Quote
 
 
 
 
red floyd
Guest
Posts: n/a
 
      12-20-2007
red floyd wrote:
> Christopher wrote:
>> The situation is that a std::list<std::set<std::string> > is being
>> iterated through. Upon certain criteria some sets become empty. I need
>> to remove the empty sets from the list.
>>
>> Is it safe to iterate through a list and call list::erase( iterator )
>> in mid iteration?

>
> Well, you can use
>
> struct set_is_empty
> {
> bool operator()(const std::set& s) const { return s.empty(); }
> };
>
> std::erase(std::remove_if(l.begin(), l.end(), set_is_empty());

crap. That should be:

l.erase(std::remove_if(l.begin(), l.end(), set_is_empty()), l.end());
>
> or else, the canonical iteration for this list is:
>
> for (it = l.begin(); it != l.end(); )
> if (it->empty())
> it = l.erase(it);
> else
> ++it;

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      12-20-2007
On Dec 20, 2:10 am, red floyd <no.s...@here.dude> wrote:
> Christopher wrote:
> > The situation is that a std::list<std::set<std::string> > is being
> > iterated through. Upon certain criteria some sets become empty. I need
> > to remove the empty sets from the list.


> > Is it safe to iterate through a list and call list::erase( iterator )
> > in mid iteration?


> Well, you can use


> struct set_is_empty
> {
> bool operator()(const std::set& s) const { return s.empty(); }
> };


> std::erase(std::remove_if(l.begin(), l.end(), set_is_empty());


Which could be unnecessarily expensive. In the case of
std::list, the canonical form is:

l.remove_if( set_is_empty() ) ;

However, the original poster said that sets "become" empty
during his iteration, so this can't be used.

> or else, the canonical iteration for this list is:


> for (it = l.begin(); it != l.end(); )
> if (it->empty())
> it = l.erase(it);
> else
> ++it;


Adopted to his case, you'd add braces and put the if at the end
of the loop. (Also, I'd write this with a while, rather than a
for. Something like:

std::list<...>::iterator iter = l.begin() ;
while ( iter != l.end() ) {
// processing...
if ( iter->empty() ) {
iter = l.erase( iter ) ;
} else {
++ iter ;
}
}

I'd prefer even more if that if could be replaced with a ?: on
the right side of an assignment, since the most important aspect
here is the update of the iterator, and not how it's being
updated, but I can't think of a nice way of doing this off hand.

--
James Kanze (GABI Software) email:
Conseils en informatique orient閑 objet/
Beratung in objektorientierter Datenverarbeitung
9 place S閙ard, 78210 St.-Cyr-l'蒫ole, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
cgspwei@gmail.com
Guest
Posts: n/a
 
      12-20-2007
On 12月20日, 下午5时40分, James Kanze <james.ka...@gmail.com> wrote:
> On Dec 20, 2:10 am, red floyd <no.s...@here.dude> wrote:
>
> > Christopher wrote:
> > > The situation is that a std::list<std::set<std::string> > is being
> > > iterated through. Upon certain criteria some sets become empty. I need
> > > to remove the empty sets from the list.
> > > Is it safe to iterate through a list and call list::erase( iterator )
> > > in mid iteration?

> > Well, you can use
> > struct set_is_empty
> > {
> > bool operator()(const std::set& s) const { return s.empty(); }
> > };
> > std::erase(std::remove_if(l.begin(), l.end(), set_is_empty());

>
> Which could be unnecessarily expensive. In the case of
> std::list, the canonical form is:
>
> l.remove_if( set_is_empty() ) ;

That is what I found in MSDN,
remove_if is a STL algorithm which removes all elements from the range
(First,Last) that cause the predicate to return true. It returns an
iterator equal to Last - n, where n = number of elements removed. The
last n elements of the range have undefined values. The size of the
container remains the same.
But there is a method named remove_if in std::list.
template<class Predicate>
void remove_if(
Predicate _Pred
)
Erases elements from a list for which a specified predicate is
satisfied.
I didn't know there is a method named remove_if in the std::list. Can
any one told me why there is no similar method in vector ?

Thanks in advance,
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      12-20-2007
On Dec 20, 12:40 pm, "cgsp...@gmail.com" <cgsp...@gmail.com> wrote:
> On 12鏈20鏃, 涓嬪崍5鏃40鍒, James Kanze <james.ka...@gmail.com> wrote:


> > On Dec 20, 2:10 am, red floyd <no.s...@here.dude> wrote:


> > > Christopher wrote:
> > > > The situation is that a std::list<std::set<std::string> > is being
> > > > iterated through. Upon certain criteria some sets become empty. I need
> > > > to remove the empty sets from the list.
> > > > Is it safe to iterate through a list and call list::erase( iterator )
> > > > in mid iteration?
> > > Well, you can use
> > > struct set_is_empty
> > > {
> > > bool operator()(const std::set& s) const { return s.empty(); }
> > > };
> > > std::erase(std::remove_if(l.begin(), l.end(), set_is_empty());


> > Which could be unnecessarily expensive. In the case of
> > std::list, the canonical form is:


> > l.remove_if( set_is_empty() ) ;


> That is what I found in MSDN,
> remove_if is a STL algorithm which removes all elements from the range
> (First,Last) that cause the predicate to return true. It returns an
> iterator equal to Last - n, where n = number of elements removed. The
> last n elements of the range have undefined values. The size of the
> container remains the same.
> But there is a method named remove_if in std::list.
> template<class Predicate>
> void remove_if(
> Predicate _Pred
> )
> Erases elements from a list for which a specified predicate is
> satisfied.
> I didn't know there is a method named remove_if in the std::list. Can
> any one told me why there is no similar method in vector ?


Because you don't need it, and it's not directly supported by
the underlying data structure.

--
James Kanze (GABI Software) email:
Conseils en informatique orient茅e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S茅mard, 78210 St.-Cyr-l'脡cole, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Struts - Problem with nested iteration or double iteration Rudi Java 5 10-01-2008 03:30 AM
for_each iteration in a std::list adds a new element and nextiteration crashes Javier C++ 0 04-18-2008 08:47 AM
how to Update/insert an xml element's text----> (<element>text</element>) HANM XML 2 01-29-2008 03:31 PM
removing an element during iteration error brekehan C++ 2 03-14-2007 08:07 PM
Remove parent element with a child element matching a given rule patrizio.trinchini@googlemail.com XML 4 08-22-2006 11:31 AM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57