Jump to content




[LUA] [Table help] Removing a table from a table in a loop


  • You cannot reply to this topic
6 replies to this topic

#1 remiX

  • Members
  • 2,076 posts
  • LocationSouth Africa

Posted 31 December 2012 - 05:24 AM

Hey guys, I've been really bored lately so I'm just messing around making random things.
At the moment I'm making a spaceship game or whatever just for fun (yes I know, there are already some but I need to extend my lua knowledge)..

Ok, so now my problem when I try remove a table within a table (for the shots that you shoot) it does remove it (i think but then errors out).
The way I thought (the only way I knew of how to do it) of how to update the shots separately and properly was using tables,
by adding the X and Y position of the shot in a table.

If I haven't made myself clear, just copy the code and test it and look at the number at the bottom right, that is the count of how many shots have been fired.
Now eventually that number will go into the thousands and I need a way to remove the shot once it's off the screen.

Spoiler

I have only tried this but it errors out on this line: "term.setCursorPos(t_shots[i].curX, t_shots[i].curY)"

function update()
    if #t_shots > 0 then
        for i = 1, #t_shots do
            if t_shots[i].curX and t_shots[i].curY then
                term.setCursorPos(t_shots[i].curX, t_shots[i].curY)
                write(" ")
                t_shots[i].curY = t_shots[i].curY - 1
                term.setCursorPos(t_shots[i].curX, t_shots[i].curY)
                write("o")
                if t_shots[i].curY == 0 then
               	 table.remove(t_shots, i) -- I think it does remove the table, but then setting the cursor position errors out
                end
            end
        end
    else
        shot = false
    end
end

Also, now and then I've been getting a Java error. It keeps disappearing before I can take a screenshot of it and I have no clue what is causing it.

#2 GopherAtl

  • Members
  • 888 posts

Posted 31 December 2012 - 05:45 AM

removing items in an index loop like this doesn't really work, you'll end up skipping items every time you remove one and then crash when it tries to continue past the new end of the loop because the end range for the for loop doesn't update.

One way to fix this is to replace the for loop with a while loop, and manage the index yourself. Example:

local function update(myArray)
  local i=1
  while i<=#myArray do
    --do update stuff

    --check if the current element is 'dead'
    if isElementDead(myArray[i]) then
	  --it is, so delete it
	  table.remove(myArray,i)
    else
	  --it ISN'T, so incremement i.
	  i=i+1
    end
  end
end

Note that when this code removes the current item from the array, it does not increment i. Removing the item at i will move the item at i+1 up to i, if there is one, so the next pass you'll want to look at i again. If i was the last item, then the while check will fail next time and end the loop.

#3 remiX

  • Members
  • 2,076 posts
  • LocationSouth Africa

Posted 31 December 2012 - 06:01 AM

Using a while loop definitely helps.

Fixed it with this function:

function update()
    i = 1
    while i <= #t_shots do
        term.setCursorPos(t_shots[i].curX, t_shots[i].curY)
        write(" ")
        t_shots[i].curY = t_shots[i].curY - 1
        term.setCursorPos(t_shots[i].curX, t_shots[i].curY)
        write("o")
        if t_shots[i].curY == 0 then
            --it is, so delete it
            table.remove(t_shots,i)
        end
        i=i+1
    end
end

Thanks :>

#4 GopherAtl

  • Members
  • 888 posts

Posted 31 December 2012 - 06:45 AM

you'll fail to update an item when you delete one, because you ignored the bit about not incrementing i when you delete an item.

Explanation:

list has 3 items... {"a", "b", "c"}

loop over them, when i==1, you remove "a". The list is now

{"b", "c"}

and then you increment i to 2. "b" should update next, but it's now index 1, but you incremented i to 2, so it'll skip "b" and update "c".

#5 remiX

  • Members
  • 2,076 posts
  • LocationSouth Africa

Posted 31 December 2012 - 07:55 AM

I see what you mean, but it's updating fine and removes them fine. When all the 'shots' are gone, it says the amount of values in the table is 0.

It updates every 0.1 seconds so it goes fast

#6 GopherAtl

  • Members
  • 888 posts

Posted 31 December 2012 - 07:58 AM

In your case it's a minor thing, the worst result is that a few bullets move a bit slower or live a bit longer than they should. Just pointing it out as in other contexts it can be a major problem, for example, if this list you were removing things from in the loop were coroutines, then the skipped coroutines could miss some events entirely.

#7 ChunLing

  • Members
  • 2,027 posts

Posted 01 January 2013 - 12:02 AM

I always just use a decrementing loop when I'm going to be removing elements from the table.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users