logical issue with lists and removing them

Just starting out? Need help? Post your questions and find answers here.
jerico2day
User
User
Posts: 37
Joined: Mon Jul 13, 2009 5:41 pm

logical issue with lists and removing them

Post by jerico2day »

The following code should delete an element and all child elements. It works fine if I don't reset the list each time I add an element (I reset it as I want new elements up front). However, when I reset the list and add an element, when it goes to delete it won't delete the requested ID, just the child ID. Any ideas why this is happening? I think I just don't understand something...

Code: Select all

Structure object
  id.l
  parent.l
EndStructure

Global NewList objects.object()
ResetList(objects())
AddElement(objects())
objects()\id = 1
objects()\parent = 0
ResetList(objects())
AddElement(objects())
objects()\id = 2
objects()\parent = 1
ResetList(objects())
AddElement(objects())
objects()\id = 3
objects()\parent = 2

Procedure delete_object(id.l)
  ForEach objects()
    If objects()\id = id
      DeleteElement(objects())
    ElseIf objects()\parent = id
      delete_object(objects()\id)
    EndIf
  Next  
EndProcedure

delete_object(2)

ForEach objects()
  Debug "ID: " + Str(objects()\id) + " :: Parent: " + Str(objects()\parent)
Next
Trond
Always Here
Always Here
Posts: 7446
Joined: Mon Sep 22, 2003 6:45 pm
Location: Norway

Re: logical issue with lists and removing them

Post by Trond »

It's because the ForEach loop uses the list's internal counter. When you use multiple nested ForEach on the same list, it may not behave as you would expect. In your case delete_object() calls itself from within ForEach objects(), triggering a new ForEach objects() that runs inside the first one, but with the same "loop counter" (the list's current selected element).

A ResetList() on the list after the recursive call makes it work correctly, but the result is a giant performance hit for large lists, as the loop will look at each element several times. You should consider structuring your data different.

Code: Select all

Procedure delete_object(id.l)
  ForEach objects()
    If objects()\id = id
      DeleteElement(objects())
    ElseIf objects()\parent = id
      delete_object(objects()\id)
      ResetList(objects())
    EndIf
  Next
EndProcedure
jerico2day
User
User
Posts: 37
Joined: Mon Jul 13, 2009 5:41 pm

Re: logical issue with lists and removing them

Post by jerico2day »

Hmm, well I ran some tests and it looks like on my computer I can delete about 1000 nested elements within about 150-180ms, this is pretty good for what I'm using it for (deleing an object won't be a frequent event and it's very unlikely I'll have more than 2 or 3 nested elements and 100 total).

I'm going to stick with it for now. I figured something like this was happening but I couldn't figure out a solution. Thanks!
Post Reply