Table isn't looping through all its values?

Here’s the deal, I’m making a system in which if a player doesn’t own a move it will be removed from their unlocked moves table. However, my for loop isn’t looping through all of them, so if a player has a move that he doesn’t own and the for loop doesn’t check it, the script will error and the player will glitch. Here, take a look yourself:
immagine_2021-08-20_022130
It counts a total of 55 values, but it loops through only 28. Code:

warn("Total moves: "..#SlotTable.Unlockables.Moves);
local TempCounted = 0;
for Index, Move in ipairs(SlotTable.Unlockables.Moves) do
	TempCounted += 1;
	local MoveFolder = ServerStorage.Everything.Moves:FindFirstChild(Move);
	if MoveFolder == nil or (EconomyTable.Level < MoveFolder.Level.Value) then
		table.remove(SlotTable.Unlockables.Moves, Index);
	end;
end;
warn("Moves counted: "..TempCounted);

Am I interrupting the loop somehow? It’s so weird, I never got this problem before and it’s annoying me. Thanks in advance.

1 Like

You are removing 28 moves with the first 28 iterations of the loop. That leaves 27 elements in the table, and the loop stops. Try a repeat/until loop, only incrementing index when you don’t remove that row.

for / ipairs is not a good solution when using table.remove, since the original index will not be updated.
I had the same problem some time ago and I got the correct approach for this:

I tried something similar, but it’s like the other 27 indexes are completely ignored and don’t exist:

        print(#SlotTable.Unlockables.Moves);
		print(SlotTable.Unlockables.Moves[29]); -- prints "Meteor Crash"
		local TempCounted = 0;
		for Index = 1, #SlotTable.Unlockables.Moves, 1 do
			print(Index); -- Gets to 29 and breaks
			local Move = SlotTable.Unlockables.Moves[Index]; -- Errors at index 29 and above
			TempCounted += 1;
			local MoveFolder = ServerStorage.Everything.Moves:FindFirstChild(Move);
			if MoveFolder == nil or (EconomyTable.Level < MoveFolder.Level.Value) then
				table.remove(SlotTable.Unlockables.Moves, Index);
			end;
		end;
		print(TempCounted);

I suppose another option is to look at and remove the lines from the table in reverse order. Deleting the last row does not mess up the index of the rest of the table.

It works like this

Index = 1
Delete row 1
Old row 2 is now row 1
Index = 2
Ignore the new row 1
Delete row 2

Hope this helps.

3 Likes

OH I understood now. I was so confused. Thanks a lot.

1 Like

so in a repeat/until loop, you would keep deleting row 1 until you like it, then increase index to 2 and keep going until Index >= #table

edit: index could be greater than size of table if you delete the last row.

1 Like

Alright I fixed it thanks to your explanation. Here is the correct code:

local ToRemove = 1;
for Index = 1, #SlotTable.Unlockables.Moves, 1 do
	local Move = SlotTable.Unlockables.Moves[ToRemove];
	local MoveFolder = ServerStorage.Everything.Moves:FindFirstChild(Move);
	if MoveFolder == nil or (EconomyTable.Level < MoveFolder.Level.Value) then
		table.remove(SlotTable.Unlockables.Moves, ToRemove);
	else
		ToRemove += 1;
	end;
end;

I will mark this reply as solution so other people can find it easily, but it’s actually thanks to you if I understood how to do it.

2 Likes