Removing Value From Table

Which way should I use to remove a value from a table?

local Table = {"a","b","c"}
table.remove(Table,1)

or

Table[1] = nil

Would one of these ways be able to cause a memory leak?

17 Likes

Both are fine, but perform differently.

local function output(tab)
	for i, v in pairs(tab) do
		print(i, "=", v)
	end
end

local t1 = {"a", "b", "c"}

table.remove(t1, 2)
output(t1) -- 1 = a, 2 = c

local t2 = {"a", "b", "c"}

t2[2] = nil
output(t2) -- 1 = a, 3 = c
58 Likes

so with the second way,

since t2[2] == nil, wouldnt it be taking up data still?

3 Likes

Behind the sceens, tables are split up into 2 poritions: index > 0 is an array, any other key is a hash table. Since it would have to use the largest index to allocate memory for the array, it would. But this works on powers of 2. source (about tables)

It comes down to use case, but you shouldn’t have to worry about any of this unless you’re working with a large number of elements. If you don’t care about order, but don’t want gaps, fast remove would be the way to go for large sets.

Someone may be able to expand on that and/or correct me.

5 Likes

Hm, is this also the case with tables that uses objects as indexes?

If so, how would I prevent gaps in those types of tables?

1 Like

If you’re using anything other than integers (which includes negative), what even constitutes gaps? You’d have to iterate over them using something like pairs, which wouldn’t show up if the key had a nil value.

You’d have to be more specific for what you’re looking for in this case.

2 Likes
local Table = {Player1=true,Player2=true,Player3=true}
Table.Player1 = nil
Table.Player2 = nil

Isn’t it possible for something like this to take up memory and cause a leak? You said for integers -
Since it would have to use the largest index to allocate memory for the array, it would.

Would it for something like this case?

1 Like

If you use anything other than a positive integer (n > 0), it’s put through the hashing function; this does not play a role in the array portion of the table. No memory leak would happen in this case.

3 Likes

Thank you!

2 Likes

Make sure to mark his solution as correct so others having the same problem can find the solution quicker. :smiley:

Oh, so when you use table.remove() - it reassigns the values to the indexes? Basically re-orders?

It takes everything above the remove index and shifts it back by one, filling in the gap left by the removed element. But if you had a space ahead, that space will still exist relative to where it was.

2 Likes

I currently have an issue with my code, but that’s because i don’t really know how to fix it.
I have a contestants table and a queue table. But if i do:

for i, player in pairs(contestants) do
	if player then
		table.remove(contestants ,i)
	end
end 

that wouldn’t really work, would it? Since i’d remove most likely the first value, effectively reordering, so that the 2 now is 1, 3 is now 2 etc. so it would skip over the reasigned one and go to the i = 2, and so on. So in this case i would need to use the player = nil, or some other way.
Or i’m misinterpreting something?

2 Likes

Depending on how/where you reference contestants, you should be able to just set the variable to a blank table. contestants[i] = nil would work in this case. Another option is iterating from the back of the table, so when you remove an element it doesn’t change the unchecked element order.

for i = #contestants, 1, -1 do
	if contestants[i] then
		table.remove(contestants, i) -- everything shifted has already been checked
	end
end

The problem with using the nil method is that there will be holes, so if you use the index in some meaningful way it may not have the desired result.

There is also fast remove that I mentioned before, and maybe even other weird ways, but they all might behave differently.

7 Likes

Ok, yeah, the removal of objects in decreasing order could also work, but i’ll try with nil too, see how they compare for my application. But then i mentioned the queue too, and the idea with that is when player joins when the game is running, he can click play and he will be thrown in the next match. so i could MAYBE do contestants = {} after the match ends, but i can’t do that to queue - i need to remove the players that were in the previous match, but leave those who joined the queue while the match was running.
I could just leave the players in the queue, but i preferred this previously mentioned option - it’s the “plan A” if you will.

You can also recheck the index after the remove if you need to go up and don’t want nils.

Perhaps a while in stead of an if condition for the removal inside your for loop?

local Table = {"a","b","c"}
Table[1] = nil

Will cause a memory leak because the table size will be 3, you’re just setting the value at index 1 to nil