I'm trying to remove 3 Instances from this table, the Script and two parts named Base and Sort individually, however in the first loop, the Instance Sort is ignored, for whatever reason. But in the second loop, the Instance Sort is included. I'm really confused. I thought that maybe the game didn't fully load yet, and that Sort wasn't loaded, so i added this repeat loop to make sure that there are only 13 instances in the table (the number of children), but it still didn't work. Every child's name is printed except for Sort.
Server script:
local parts repeat parts = script.Parent:GetChildren() until #parts == 13 for i, child in pairs(parts) do print(child.Name) if child == script or child.Name == 'Sort' or child.Name == 'Base' then table.remove(parts, i) end end for i, child in pairs(parts) do child.SurfaceGui.TextLabel.Text = child.Name end
I also get an error that states that Sort doesn't have a child named SurfaceGui, because, well, it doesn't, but Sort shouldn't be in the table at all.
First and foremost you should use ipairs
instead of pairs
for arrays, as pairs
is not guaranteed to iterate in order. However that is not what is causing an issue here.
Problem is with table.remove
. What it is doing its removing an element from the table and moves all elements to the "right" of this part, one space "left". (Left and right is just imaginary, as you were to write all elements on paper)
So when you iterate through your table, you remove element called Base
or the script
. Elements are moved, and Sort
is being moved into that spot. Since next iteration checks the next element on the paper, Sort
slips under the radar.
To solve this, you should use a dictionary or remove just one element at a time. Other option is to replace an element with false
, and check it in the next loop. On the other hand, If you put nil
as a value, your array will become a dictionary. This will solve your issue as well.
for i, child in pairs(parts) do print(child.Name) if child == script or child.Name == 'Sort' or child.Name == 'Base' then parts[i] = nil --by doing this your array will become a dictionary, and you cannot use #parts to count elements anymore. end end for i, child in pairs(parts) do child.SurfaceGui.TextLabel.Text = child.Name end
Have a nice scripting session.
Edit - visual representation (just an example)
--[[ Array [1] [2] [3] [4] [5] [6] Part Base Sort Part Part script table.remove METHOD 1. Loop checks 1st element - no action 2. Loop checks 2nd element - Base gets removed, elements to the right are moved Array [1] [2] [3] [4] [5] Part Sort Part Part script 3. Loop checks 3rd element - notice how `Sort` is now at 2nd position, therefore it is not checked. nil METHOD 1. Loop checks 1st element - no action 2. Loop checks 2nd element - index gets removed, elements ARE NOT moved Array [1] [nil] [3] [4] [5] [6] Part [removed] Sort Part Part script Since index [2] is now missing, array becomes a dictionary. Elements are now not in proper order (2 is gone), #parts cannot be used. 3. Loop checks 3rd element - `Sort` found! --]]
I hope this explains it better. To preserve an array you would need to put something at index no 2. Distinction between arrays and dictionaries is subtle, and to lua everything is a dicionary. Think of it this way : A table is an array ONLY when all its elements are indexed with numbers from 1, without any numbers missing.