Removing objects in a table?

I want to create objects on the fly but now wonder how I can handle their removal?

I normally would create the objects in a table like this:

objects[#objects+1]=display.newCircle(…)

objects[#objects+1]=display.newRect(…)

objects[#objects+1]=display.newImageRect(…)

But to save memory I want to delete objects when they are not needed anymore.

But I also need to cycle through the objects table a lot to check for collisions and stuff.

What is the best practice to do this without messing up the objects index in the table and still removing them correctly and nil them out?

I almost 100% of the time store objects in tables by their ids, then maintenance is easy.  I only use numerically indexed tables for special cases or where order is paramount.

Example:

-- Semi-elaborate example showing some very important principles for reducing your memory footprint -- and for maintaining clean code. local physics = require "physics" physics.start() physics.setGravity(0,0) local objCountTarget = 10 local myObjects = {} local countObjs() local count = 0 for k,v in pairs(myObjects) do count = count + 1 end return count end -- unified collision handler local function onCollision( self, event ) myObjects[self] = nil self:removeEventListener("collision") display.remove(self) return false end local randomMaker() local x = math.random(-300,300) local y = math.random(-300,300) local tmp = display.newCircle( x, y, 10 ) physics.addBody( tmp ) -- store in table by object ID myObjects[tmp] = tmp tmp.collision = onCollision tmp:addEventListener( "collision" ) -- not great to mix transitions with physics, but doing so for this example to keep simple transition.to( tmp, { x = display.contentCenterX, y = tmp.contentCenterY } ) end local function enterFrame() if( countObjs() \< objCountTarget ) then randomMaker() end end Runtime:addEventListener( "enterFrame", enterFrame )

Assuming this example has no syntax errors, it will strive to keep 10 circles on the screen, taking 10 frames to get there, but subequently keeping it so every frame (except in the case where removals happen in the same frame).  

These circles will appear randomly on the screen and move to the middle.

When circles touch, they self delete, using a common collision Listener.

This code is fast, clean, and will not leak

That really is some great info here! Thank you very much!

While working with this I wonder how I can access myObjects from somewhere else in the code?

– store in table by object ID
myObjects[tmp] = tmp

With an index like this:

myObjects[#myObjects] this now isn’t working… so how does the data structure look here for this table and how can I access the latest object in the table from somewhere else?

That’s one of the downsides using hash (string) indices instead of numerical ones.

If the order of the objects is important, you should use numerical indices. If you want to remove a specific object, you call this construct:

table.remove(tableName, table.indexOf(tableName, object))

If you just need a table containing all objects, so you can loop over them and their order and the number of objects in the table is irrelevant, you could use hash indices as roaminggamer mentioned. Removal of objects is pretty here.

I almost 100% of the time store objects in tables by their ids, then maintenance is easy.  I only use numerically indexed tables for special cases or where order is paramount.

Example:

-- Semi-elaborate example showing some very important principles for reducing your memory footprint -- and for maintaining clean code. local physics = require "physics" physics.start() physics.setGravity(0,0) local objCountTarget = 10 local myObjects = {} local countObjs() local count = 0 for k,v in pairs(myObjects) do count = count + 1 end return count end -- unified collision handler local function onCollision( self, event ) myObjects[self] = nil self:removeEventListener("collision") display.remove(self) return false end local randomMaker() local x = math.random(-300,300) local y = math.random(-300,300) local tmp = display.newCircle( x, y, 10 ) physics.addBody( tmp ) -- store in table by object ID myObjects[tmp] = tmp tmp.collision = onCollision tmp:addEventListener( "collision" ) -- not great to mix transitions with physics, but doing so for this example to keep simple transition.to( tmp, { x = display.contentCenterX, y = tmp.contentCenterY } ) end local function enterFrame() if( countObjs() \< objCountTarget ) then randomMaker() end end Runtime:addEventListener( "enterFrame", enterFrame )

Assuming this example has no syntax errors, it will strive to keep 10 circles on the screen, taking 10 frames to get there, but subequently keeping it so every frame (except in the case where removals happen in the same frame).  

These circles will appear randomly on the screen and move to the middle.

When circles touch, they self delete, using a common collision Listener.

This code is fast, clean, and will not leak

That really is some great info here! Thank you very much!

While working with this I wonder how I can access myObjects from somewhere else in the code?

– store in table by object ID
myObjects[tmp] = tmp

With an index like this:

myObjects[#myObjects] this now isn’t working… so how does the data structure look here for this table and how can I access the latest object in the table from somewhere else?

That’s one of the downsides using hash (string) indices instead of numerical ones.

If the order of the objects is important, you should use numerical indices. If you want to remove a specific object, you call this construct:

table.remove(tableName, table.indexOf(tableName, object))

If you just need a table containing all objects, so you can loop over them and their order and the number of objects in the table is irrelevant, you could use hash indices as roaminggamer mentioned. Removal of objects is pretty here.