www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Removing items from an Array

reply "Mars" <- -.-> writes:
Hello everybody.
Once again I have a little question, this time about removing 
items from an assoc array in a foreach.

Why does the following code:
http://pastebin.com/65P9WDNS
Result in this output:
http://pastebin.com/4FzEE1zi

It seems rather strange to me. I'd expect the foreach_reverse to 
go over the array from the end to the beginning, and when I 
remove stuff from it, it shouldn't be a problem. But apparently 
it is.

Mars
Feb 17 2012
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, February 17, 2012 11:00:36 Mars wrote:
 Hello everybody.
 Once again I have a little question, this time about removing
 items from an assoc array in a foreach.
 
 Why does the following code:
 http://pastebin.com/65P9WDNS
 Result in this output:
 http://pastebin.com/4FzEE1zi
 
 It seems rather strange to me. I'd expect the foreach_reverse to
 go over the array from the end to the beginning, and when I
 remove stuff from it, it shouldn't be a problem. But apparently
 it is.

I don't believe that removing elements from an AA while iterating over it is safe. - Jonathan M Davis
Feb 17 2012
prev sibling next sibling parent "Mars" <- -.-> writes:
On Friday, 17 February 2012 at 10:13:00 UTC, Jonathan M Davis 
wrote:
 I don't believe that removing elements from an AA while 
 iterating over it is safe.

 - Jonathan M Davis

Well, no. But from my experience it's okay from bottom to top... at least in other languages. What would be the alternative? Maybe build a new array while iterating, and set it after the loop?
Feb 17 2012
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
foreach_reverse isn't going to help you much since AA's do not save
the order of the keys. A quick workaround:
http://pastebin.com/KkECqwUU

Others probably know efficient ways to do this.
Feb 17 2012
prev sibling next sibling parent Andrea Fontana <advmail katamail.com> writes:
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

Usually in other languages iterators are safe.

Il giorno ven, 17/02/2012 alle 11.35 +0100, Mars ha scritto:

 On Friday, 17 February 2012 at 10:13:00 UTC, Jonathan M Davis=20
 wrote:
 I don't believe that removing elements from an AA while=20
 iterating over it is safe.

 - Jonathan M Davis

Well, no. But from my experience it's okay from bottom to top...=20 at least in other languages. What would be the alternative? Maybe build a new array while=20 iterating, and set it after the loop?

Feb 17 2012
prev sibling next sibling parent James Miller <james aatch.net> writes:
AAs don't keep the key order, so when you delete something out of it,
what ever system iterates to the next pointer gets confused. Its
generally a bad idea to modify an array as you loop through it.

--
James Miller
Feb 17 2012
prev sibling next sibling parent "Mars" <- -.-> writes:
On Friday, 17 February 2012 at 13:33:25 UTC, James Miller wrote:
 AAs don't keep the key order, so when you delete something out 
 of it,
 what ever system iterates to the next pointer gets confused. Its
 generally a bad idea to modify an array as you loop through it.

 --
 James Miller

Too bad. So, what would be the correct way to do this? I mean... it's not that uncommon, to have this problem. Are creating a new array while iterating over it, or creating a list of elements to remove, and removing them afterwards, the only ways to do this?
Feb 17 2012
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Friday, February 17, 2012 14:44:42 Mars wrote:
 On Friday, 17 February 2012 at 13:33:25 UTC, James Miller wrote:
 AAs don't keep the key order, so when you delete something out
 of it,
 what ever system iterates to the next pointer gets confused. Its
 generally a bad idea to modify an array as you loop through it.
 
 --
 James Miller

Too bad. So, what would be the correct way to do this? I mean... it's not that uncommon, to have this problem. Are creating a new array while iterating over it, or creating a list of elements to remove, and removing them afterwards, the only ways to do this?

That's the way that I'd do it. - Jonathan M Davis
Feb 17 2012
prev sibling next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Fri, 17 Feb 2012 08:44:42 -0500, Mars <- -.-> wrote:

 On Friday, 17 February 2012 at 13:33:25 UTC, James Miller wrote:
 AAs don't keep the key order, so when you delete something out of it,
 what ever system iterates to the next pointer gets confused. Its
 generally a bad idea to modify an array as you loop through it.

 --
 James Miller

Too bad. So, what would be the correct way to do this? I mean... it's not that uncommon, to have this problem. Are creating a new array while iterating over it, or creating a list of elements to remove, and removing them afterwards, the only ways to do this?

If you are interested in an alternative implementation that does allow this, see here: www.dsource.org/projects/dcollections One of the features is "Removal while traversing." In particular pay attention to the purge and keyPurge functions of the HashMap class and its usage. The docs are woefully underdeveloped, but you can see how its used here: http://www.dsource.org/projects/dcollections/browser/branches/d2/concepts.txt#L81 -Steve
Feb 17 2012
prev sibling parent James Miller <james aatch.net> writes:
On 18 February 2012 05:30, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 On Friday, February 17, 2012 14:44:42 Mars wrote:
 On Friday, 17 February 2012 at 13:33:25 UTC, James Miller wrote:
 AAs don't keep the key order, so when you delete something out
 of it,
 what ever system iterates to the next pointer gets confused. Its
 generally a bad idea to modify an array as you loop through it.

 --
 James Miller

Too bad. So, what would be the correct way to do this? I mean... it's not that uncommon, to have this problem. Are creating a new array while iterating over it, or creating a list of elements to remove, and removing them afterwards, the only ways to do this?

That's the way that I'd do it. - Jonathan M Davis

Pretty much. To expand on Jonathan's answer, the problem with iterating and deleting is that the conditions when the loop started are not the same as the conditions at the middle or end. With a fixed-size array, you can do it safely assuming you write the proper conditions, and you don't accidentally convert it to a slice. With removal, taking a small memory hit to create a new array tends to be worth it, since you can reclaim the memory from the old one (which is presumably bigger). This is the kind of condition that memory "scratch" spaces are advocated for (often used in game dev, due to massive data processing requirements at speed). However, I don't suggest implementing said scratch space in D, since the GC pretty much does this anyway.
Feb 20 2012