Why is my table going in such weird order when I assign the order?

My game is about blinking. If you blink a new object spawns in. They all spawn in order so I can detect when the last one spawns in so I can trigger an event. For some reason it skips from 4 to 8? Everything goes in order quite fine to start with (the {…} is the table with the remaining objects)

Here’s my script

game.ReplicatedStorage.OnBlink.OnServerEvent:Connect(function(plr)
	
	local orderTable = {}
	local key,value
	
	for i,v in ipairs(game.ServerStorage.Objects:GetChildren()) do
	
		table.insert(orderTable,v:GetAttribute("Order"),v.Name)

	end
	
	print(orderTable)
	key,value = next(orderTable)
	print(key,value)
	
	if game.ServerStorage.Objects:FindFirstChild(value) then
		
		if game.ServerStorage.Objects:FindFirstChild(value):GetAttribute("Order") == key then
			
			game.ServerStorage.Objects:FindFirstChild(value).Parent = workspace
			
		end


	end

	
end)

image

What can I do to fix this? There are no errors.

You made this thread yesterday.

The numerical order of indexes is not technically how data is ordered in RAM. Lua table entries have no official order in RAM. A table is linked together as allocations are made, so the next function can be understood to be pulling the next-allocated memory address in RAM corresponding to a table element, which is determined at the time of allocation and not by the value of the index.

The reason an iterator function like ipairs returns table elements “in order” is because that function attempts to index the table using counting numbers (what has been defined as “in order” to humans). In the same way, if you want to get elements in order, you will need to index the table “in order.” Since the table elements are indexed with numerical keys, orderTable[1] will get you the first item in the list, but next(orderTable) will simply give you the first element added to the table (probably), regardless of its index.

I solved that issue, now it’s a different thing.

It will give me the first item, and not return an error right?
Because doesn’t that use the key?
If I do ordertable[1] it just returns nil after the object assigned the key “1” is removed from the table.

If your table is removing the first indexes, then, yes, that would cause an error.

Some solutions to that problem could be to count up from 1 until a valid index is found, which is quick on smaller arrays but will get progressively slower:

local key = 1
while not orderTable[key] do
	key += 1
end
local value = orderTable[key]

…or to iterate through the entire table with pairs and select whichever item in the list has the lowest index, a process that would be slow on larger arrays but speed up over time.

local key = math.huge
for _key in pairs(orderTable) do
	if _key < key then
		key = _key
	end
end
local value = orderTable[key]

These two methods are probably not equivalent in terms of performance, and I haven’t done any benchmarking, but unless you’re running these calculations hundreds of thousands of times per second, whichever you use comes down to preferences.

1 Like

A quick note to my previous post that may change which algorithm you choose to use that I didn’t think of initially: if orderTable is empty, the first algorithm will hang until the script execution timeout aborts it (that is to say, it would be bad), but the second would simply have value be nil rather than crashing.

To fix that problem on the first algorithm, stopping the search once the key hit a certain number that could never be achieved legitimately in run time would prevent it from searching forever.

What I personally do in these situations & what I consider most performant is convert the dictionary (with numeric indices) into an array and then sort that converted array via the table library function sort. Take the following for example.

local orderTable = {}

for _, value in ipairs(game.ServerStorage.Objects:GetChildren()) do
	table.insert(orderTable, {value:GetAttribute("Order"), value.Name})
end

table.sort(orderTable, function(left, right)
	return left[1] < right[1]
end)

for _, orderArray in ipairs(orderTable) do
	print(orderArray[1], orderArray[2])
end

This would print the original dictionary’s contents in the ascending order (smallest to largest) of its numerical indices.