1

# Why is the Instance Sort not being removed in this table?

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.

0
I edited my answer, I hope this explains it better. sleazel 1207 — 2mo

1
sleazel 1207
2 months ago
Edited 2 months ago

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.

0
I'm not entirely sure I understand. Yes, it works, I'll give you that, but why does using a dictionary fix it? How does parts[i] = nil change the array into a dictionary? deeskaalstickman649 388 — 2mo
0
Answer edited. sleazel 1207 — 2mo