Remove single entry from lua table

Hi,

I know how to remove everything from a table but not just one item.

So any advice would be most helpful.

I have created for objects and added them to a table, I just want to remove say the second object, I have tried various methods but none seem to work.

I tried the table.remove(roadBlocks,3) , using k,v in pairs(roadBlocks) etc and iterating backwards

Apologies for the formatting the tags dont seem to work for me.


local roadBlocks = {}

local function createRoadBlock(layer)

    local layer = layer or display.currentStage

    local roadBlockPosX = {100,220,100,200 }
    local roadBlockPosY = {50,50,430,430 }
    local roadBlockRotation ={-45,45,45,-45}

    for i =1, 4 do

    local roadBlock = display.newRect(0,0,40,5)
        roadBlock.x = roadBlockPosX[i]
        roadBlock.y = roadBlockPosY[i]
        roadBlock.rotation = roadBlockRotation[i]

        roadBlocks[roadBlock] = roadBlock
    end

    timer.performWithDelay(2000, function()

---------- remove roadblock 3 here from the table and the display object----------
    end)
end


Hi.

You can use the for k, v approach, though it will be hard to pin down a given item. You’d have to stuff an id somewhere, basically.

You probably wanted 

roadBlocks[i] = roadBlock -- or roadBlocks[#roadBlocks + 1] = roadBlock

instead of

roadBlocks[roadBlock] = roadBlock

in which case table.remove() would be fine, although you’d still have to account for objects shifting positions when you remove others.

you need to “choose” whether you want to index by object or number

if by object (as you’re presently doing):  then removal by roadBlocks[aRoadBlockObject] = nil

if by number (as per @StarCrunch):  then table.remove will work

either way you’ll likely want to store an id on each roadblock object, either because you can’t “find” the “second one” with first approach without an id, or because in the second approach an index may no longer equal its id after table.insert or table.remove

Hi,

yes thanks for the pointers.

I used the below to store in the table.

[lua] roadBlocks[#roadBlocks +1] = roadBlock [/lua]

and then I can remove any individual item by doing

[lua] table.remove(roadBlocks[2])

display.remove(roadBlocks[2])

[/lua]

Almost. What you want is

table.remove(roadBlocks, 2)

Unfortunately the part of display objects we see is a table, so a table.remove of the display object itself will fail silently. (Without additional arguments, a remove behaves like a stack pop. Usually this will not do anything, but will be extra confusing if you stuff array entries into your display object!)

Anyhow, as davebollinger and I point out, the “any individual element” must be approached with caution. Once you remove, say, element #2, suddenly elements 3, 4, etc. move down into slots 2, 3, and so on. So it will only continue to work if you remove lower and lower entries; needless to say, difficult to get right.

The ID approach would go something like this:

local function NewObject (id) local obj = display.newRect(1, 2, 3, 4) -- whatever obj.my\_id = id roadBlocks[#roadBlocks + 1] = obj return obj end local function RemoveObject (id) for i = 1, #roadBlocks do local obj = roadBlocks[i] if obj.my\_id == id then table.remove(roadBlocks, i) display.remove(obj) return end end end

and then using it:

for i = 1, NumberOfRoadBlocks do local roadBlock = NewObject("roadBlock" .. i) -- do stuff end -- other stuff -- later: RemoveObject("roadBlock2")

If you actually do need things to stay in place, I’ve got something for that too, but the above is probably simpler.

even if you correct the table.remove syntax (as per @StarCrunch), there’s another huge logic problem here, hint:  what if you reversed the order of those two calls?

Hi.

You can use the for k, v approach, though it will be hard to pin down a given item. You’d have to stuff an id somewhere, basically.

You probably wanted 

roadBlocks[i] = roadBlock -- or roadBlocks[#roadBlocks + 1] = roadBlock

instead of

roadBlocks[roadBlock] = roadBlock

in which case table.remove() would be fine, although you’d still have to account for objects shifting positions when you remove others.

you need to “choose” whether you want to index by object or number

if by object (as you’re presently doing):  then removal by roadBlocks[aRoadBlockObject] = nil

if by number (as per @StarCrunch):  then table.remove will work

either way you’ll likely want to store an id on each roadblock object, either because you can’t “find” the “second one” with first approach without an id, or because in the second approach an index may no longer equal its id after table.insert or table.remove

Hi,

yes thanks for the pointers.

I used the below to store in the table.

[lua] roadBlocks[#roadBlocks +1] = roadBlock [/lua]

and then I can remove any individual item by doing

[lua] table.remove(roadBlocks[2])

display.remove(roadBlocks[2])

[/lua]

Almost. What you want is

table.remove(roadBlocks, 2)

Unfortunately the part of display objects we see is a table, so a table.remove of the display object itself will fail silently. (Without additional arguments, a remove behaves like a stack pop. Usually this will not do anything, but will be extra confusing if you stuff array entries into your display object!)

Anyhow, as davebollinger and I point out, the “any individual element” must be approached with caution. Once you remove, say, element #2, suddenly elements 3, 4, etc. move down into slots 2, 3, and so on. So it will only continue to work if you remove lower and lower entries; needless to say, difficult to get right.

The ID approach would go something like this:

local function NewObject (id) local obj = display.newRect(1, 2, 3, 4) -- whatever obj.my\_id = id roadBlocks[#roadBlocks + 1] = obj return obj end local function RemoveObject (id) for i = 1, #roadBlocks do local obj = roadBlocks[i] if obj.my\_id == id then table.remove(roadBlocks, i) display.remove(obj) return end end end

and then using it:

for i = 1, NumberOfRoadBlocks do local roadBlock = NewObject("roadBlock" .. i) -- do stuff end -- other stuff -- later: RemoveObject("roadBlock2")

If you actually do need things to stay in place, I’ve got something for that too, but the above is probably simpler.

even if you correct the table.remove syntax (as per @StarCrunch), there’s another huge logic problem here, hint:  what if you reversed the order of those two calls?