By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,930 Members | 1,465 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,930 IT Pros & Developers. It's quick & easy.

Deleting items from std::map in a loop

P: n/a
Ok, so if I want to selectively delete items from a sequence like a
deque or vector from a for loop, I have to do something like this:

for(iter = list.begin(); iter != list.end(); ++iter)
{
if(shouldDelete(*iter))
{
iter = list.erase(iter);
--iter;
}
}

I'm trying to accomplish the same sort of thing in a map traversal.
Map's implementation of erase() doesn't return an iterator. How do I
accomplish what I'm trying to do?

Thanks,
Tim

Jul 19 '05 #1
Share this Question
Share on Google+
6 Replies


P: n/a
Tim Conkling wrote:
Ok, so if I want to selectively delete items from a sequence like a
deque or vector from a for loop, I have to do something like this:

for(iter = list.begin(); iter != list.end(); ++iter)
{
if(shouldDelete(*iter))
{
iter = list.erase(iter);
--iter;
}
}

I'm trying to accomplish the same sort of thing in a map traversal.
Map's implementation of erase() doesn't return an iterator. How do I
accomplish what I'm trying to do?

Thanks,
Tim


How about remove_if() ?

Jul 19 '05 #2

P: n/a
Tim Conkling wrote in news:bo**********@saturn.services.brown.edu:
Ok, so if I want to selectively delete items from a sequence like a
deque or vector from a for loop, I have to do something like this:

for(iter = list.begin(); iter != list.end(); ++iter)
{
if(shouldDelete(*iter))
{
iter = list.erase(iter);
--iter;
}
}

I'm trying to accomplish the same sort of thing in a map traversal.
Map's implementation of erase() doesn't return an iterator. How do I
accomplish what I'm trying to do?


cont_type::iterator iter = cont.begin(), lim = cont.end();
while ( iter != lim )
{
if( shouldDelete(*iter))
{
list.erase( iter++ );
}
else ++iter;
}

It should work for any container, even ones where you can't
do --cont.end().

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 19 '05 #3

P: n/a
On Thu, 06 Nov 2003 06:44:55 GMT, NFish <no****@nowhere.net> wrote:
Tim Conkling wrote:
Ok, so if I want to selectively delete items from a sequence like a
deque or vector from a for loop, I have to do something like this:

for(iter = list.begin(); iter != list.end(); ++iter)
{
if(shouldDelete(*iter))
{
iter = list.erase(iter);
--iter;
}
}

I'm trying to accomplish the same sort of thing in a map traversal.
Map's implementation of erase() doesn't return an iterator. How do I
accomplish what I'm trying to do?

Thanks,
Tim


How about remove_if() ?


Mutating algorithms don't work on set or map, that have const value
types.

Tom
Jul 19 '05 #4

P: n/a
"Tim Conkling" <tc*******@brown.edu> wrote in message
news:bo**********@saturn.services.brown.edu...
| Ok, so if I want to selectively delete items from a sequence like a
| deque or vector from a for loop, I have to do something like this:
|
| for(iter = list.begin(); iter != list.end(); ++iter)
| {
| if(shouldDelete(*iter))
| {
| iter = list.erase(iter);
| --iter;
| }
| }

Yes, but for std::deque and std::vector at least, it would be
much more efficient to use the std::remove_if algorithm:
list.erase( remove_if( list.begin(), list.end(), &shouldDelete )
, list.end() );

| I'm trying to accomplish the same sort of thing in a map traversal.
| Map's implementation of erase() doesn't return an iterator. How do I
| accomplish what I'm trying to do?

For information, see:
http://anubis.dkuug.dk/jtc1/sc22/wg2...losed.html#130
So this is a debated issue. Note that some implementations of
map::erase do return an interator. But it is quite easy to
work around this limitation: just use the postfix ++ operator.

The following will do:

for(iter = map.begin() ; iter != map.end() ; )
{
if(shouldDelete(*iter))
map.erase( iter++ );
else
++iter;
}

The map.erase( iter++ ) line is equivalent to:
{
IterType kill = iter;
++iter;
map.erase(kill);
}
(the 1-line form works because the postfix++ operator
modifies the iter variable and returns its previous
value *prior* to the call of the erase function ).

I hope this helps,
Ivan
--
http://ivan.vecerina.com
Jul 19 '05 #5

P: n/a
In article <bo**********@newshispeed.ch>,
"Ivan Vecerina" <pl*****************@ivan.vecerina.com> wrote:
For information, see:
http://anubis.dkuug.dk/jtc1/sc22/wg2...losed.html#130
So this is a debated issue. Note that some implementations of
map::erase do return an interator.
Fwiw, lwg #130 has now been reopened. See especially the note:
A future standard may wish to reconsider this issue.


"The future is now" is the current feeling in the lwg.

-Howard
Jul 19 '05 #6

P: n/a
Tim Conkling wrote:
Ok, so if I want to selectively delete items from a sequence like a
deque or vector from a for loop, I have to do something like this:

for(iter = list.begin(); iter != list.end(); ++iter)
{
if(shouldDelete(*iter))
{
iter = list.erase(iter);
--iter;
}
}
Now, think what's going to happen if 'shouldDelete' returns 'true' for
the very first element of the sequence...

The better way to do it would be

for(iter = list.begin(); iter != list.end();)
if(shouldDelete(*iter))
iter = list.erase(iter);
else
++iter;

or simply

list.erase(std::remove_if(list.begin(), list.end(), shouldDelete),
list_end());

These two techniques are also applicable to 'std::vector'.
I'm trying to accomplish the same sort of thing in a map traversal.
Map's implementation of erase() doesn't return an iterator. How do I
accomplish what I'm trying to do?


The truth is that 'erase' in associative containers doesn't invalidate
any iterators except those that point to elements being erased (that's
also true for 'sid::list'). For this reason, you don't really need
'map::erase' to return an iterator. Just do this

for(iter = map.begin(); iter != map.end();)
if(shouldDelete(*iter))
map.erase(iter++);
else
++iter;

This will also work for 'std::list', but won't work for 'std::vector'.

--
Best regards,
Andrey Tarasevich

Jul 19 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.