Any way to make dictionary maintain order

The code below works fine, the issue I have with it is that specifically

["General3"] = {
		["Sub1"] = {
			["G3-S1-Value1"] = {
				"Cat1",
				"Cat2",
				"Cat3"
			},
			"G3-S1-Value2",
			"G3-S1-Value3",
		},

Is not ordered, I am aware this is due to the fact that [“G3-S1-Value1”] isn’t a string however I do not know how to fix it, help is appreciated

Full code:

local UIS = game:GetService("UserInputService")

local masterTable = {
	["General1"] = {
		["Sub1"] = {
			"G1-S1-Value1",
			"G1-S1-Value2",
			"G1-S1-Value3",
		},
		["Sub2"] = {
			"G1-S2-Value1",
			"G1-S2-Value2",
			"G1-S2-Value3",
		},
		["Sub3"] = {
			"G1-S3-Value1",
			"G1-S3-Value2",
			"G1-S3-Value3",
		},
	},
	["General2"] = {
		["Sub1"] = {
			"G2-S1-Value1",
			"G2-S1-Value2",
			"G2-S1-Value3",
		},
		["Sub2"] = {
			"G2-S2-Value1",
			"G2-S2-Value2",
			"G2-S2-Value3",
		},
		["Sub3"] = {
			"G2-S3-Value1",
			"G2-S3-Value2",
			"G2-S3-Value3",
		},
	},
	["General3"] = {
		["Sub1"] = {
			["G3-S1-Value1"] = {
				"Cat1",
				"Cat2",
				"Cat3"
			},
			"G3-S1-Value2",
			"G3-S1-Value3",
		},
		["Sub2"] = {
			"G3-S2-Value1",
			"G3-S2-Value2",
			"G3-S2-Value3",
		},
		["Sub3"] = {
			"G3-S3-Value1",
			"G3-S3-Value2",
			"G3-S3-Value3",
		},
	},
}

local masterOrder = {
	"General1", "General2", "General3"
}

local subOrder = {
	"Sub1", "Sub2", "Sub3"
}

local CatOrder = {
	"Cat1", "Cat2", "Cat3"
}

local currentTable = masterTable
local tableHistory = {}
local Visible = false


function getOrderedKeys(tbl, orderReference)
	local orderedKeys = {}
	for key, _ in pairs(tbl) do
		table.insert(orderedKeys, key)
	end

	table.sort(orderedKeys, function(a, b)
		local indexA = table.find(orderReference, a) or math.huge
		local indexB = table.find(orderReference, b) or math.huge
		return indexA < indexB
	end)
	return orderedKeys
end


function assignButtonTexts(desiredTable)
	local index = 1

	if typeof(desiredTable) ~= "string" then
		local orderReference = masterOrder
		if currentTable ~= masterTable then
			orderReference = subOrder
		end
		
		
		if currentTable == masterTable["General3"]["Sub1"]["G3-S1-Value1"] then
			orderReference = CatOrder
		end
		
		local orderedKeys = getOrderedKeys(desiredTable, orderReference)
		
		for _, key in ipairs(orderedKeys) do
			local value = desiredTable[key]
			if type(value) == "table" then
				script.Parent:FindFirstChild(index).Text = key
			else
				script.Parent:FindFirstChild(index).Text = value
			end
			index += 1
		end
	else
		print(desiredTable)
		currentTable = masterTable
		table.clear(tableHistory)
		assignButtonTexts(currentTable)
	end
end

assignButtonTexts(currentTable)

local validKeys = {Enum.KeyCode.One, Enum.KeyCode.Two, Enum.KeyCode.Three}
local ascociatedNumbers = {["Enum.KeyCode.One"] = 1, ["Enum.KeyCode.Two"] = 2, ["Enum.KeyCode.Three"] = 3}

UIS.InputBegan:Connect(function(input, gp)
	if gp then return end

	if input.KeyCode == Enum.KeyCode.T then
		Visible = not Visible
		script.Parent.Enabled = Visible

		if not Visible then
			currentTable = masterTable
			table.clear(tableHistory)
			assignButtonTexts(currentTable)
		end
	end

	if input.KeyCode == Enum.KeyCode.Backspace and #tableHistory > 0 then
		currentTable = table.remove(tableHistory)
		task.wait(0.1)
		assignButtonTexts(currentTable)
	end

	if not table.find(validKeys, input.KeyCode) then return end

	local key = ascociatedNumbers[tostring(input.KeyCode)]
	table.insert(tableHistory, currentTable)

	local orderReference = masterOrder
	if currentTable ~= masterTable then
		orderReference = subOrder
	end

	local orderedKeys = getOrderedKeys(currentTable, orderReference)
	local selectedKey = orderedKeys[key]

	if selectedKey then
		currentTable = currentTable[selectedKey]
		task.wait(0.1)
		assignButtonTexts(currentTable)
	end
end)


This is a string btw.

If you want it to be ordered, you will need to make the table a list, and then store extra information separately, such as “Name”. This can be done in a separate table, like a dictionary, or as a child field in that table itself.

It might help to share more context about the problem.

Is there not a way to adapt the function that returns the orderedKeys to work with [“G3-S1-Value1”]?

When you write

["Sub1"] = {
	["G3-S1-Value1"] = {
		"Cat1"
	},
	"G3-S1-Value2",
	"G3-S1-Value3",
}

You’re really writing

["Sub1"] = {
	["G3-S1-Value1"] = {
		"Cat1"
	},
	[1] = "G3-S1-Value2",
	[2] = "G3-S1-Value3",
}

So in one case, the “G3-S1-…” is a key, and in the other it’s a value.


What I would recommend to get ordering is formatting your data to have everything be values

["Sub1"] = {
	{"G3-S1-Value1", {
		"Cat1"
	}},
	"G3-S1-Value2",
	"G3-S1-Value3",
}

but then you’d need to check the type to know whether to get the table, so this might be better:

["Sub1"] = {
	{"G3-S1-Value1", {
		"Cat1"
	}},
	{"G3-S1-Value2", {}},
	{"G3-S1-Value3", {}}
}

The second option is more consistent and easier to code. You can also use string indexing:

["Sub1"] = {
	{Name = "G3-S1-Value1", Elements = {
		"Cat1"
	}},
	{Name = "G3-S1-Value2", Elements = {}},
	{Name = "G3-S1-Value3", Elements = {}}
}

This makes it more readable when you’re accessing the elements (so you can use .Name instead of [1]).

1 Like

What do you expect it to do return when asked to order these?

  • G3-S1-Value1 : {}
  • 1 : “G3-S1-Value2”
  • 2 : "G3-S1-Value3
1 Like

Yes, I want it to be in the order as it is visually in the MasterTable

Is it sorting based on the key? and strings like “G3-S1-Value1” come before numbers like 1?

I think you are operating here based on a misunderstanding of how tables as dictionaries and tables as arrays each work. You should do a little bit of experimentation and review the comment that @BendsSpace shared.

1 Like

I wrote the code a while ago and came back to it as I need it for a game now so I dont remember exactly, its using their positions in the orderReference table to sort them I believe

Ok so anyways 2 days ago i saw a tweet saying Grok AI is very good at code, didnt believe it, gave it a shot anyways

code works immediately

here it is, no clue what it did, but it works

local UIS = game:GetService("UserInputService")

local masterTable = {
	["General1"] = {
		["Sub1"] = {
			{Name = "G3-S1-Value1", Elements = {"Cat1", "Cat2", "Cat3"}},
			{Name = "G3-S2-Value2", Elements = {}},
			{Name = "G3-S3-Value3", Elements = {}}
		},
		["Sub2"] = {
			{Name = "G3-S1-Value1", Elements = {}},
			{Name = "G3-S2-Value2", Elements = {}},
			{Name = "G3-S3-Value3", Elements = {}}
		},
		["Sub3"] = {
			{Name = "Just One here", Elements = {}},
		},
	},
	["General2"] = {
		["Sub1"] = {
			{Name = "G3-S1-Value1", Elements = {"Cat1", "Cat2", "Cat3"}},
			{Name = "G3-S2-Value2", Elements = {}},
			{Name = "G3-S3-Value3", Elements = {}}
		},
		["Sub2"] = {
			{Name = "G3-S1-Value1", Elements = {}},
			{Name = "G3-S2-Value2", Elements = {}},
			{Name = "G3-S3-Value3", Elements = {}}
		},
		["Sub3"] = {
			{Name = "Just One here", Elements = {}},
		},
	},
	["General3"] = {
		["Sub1"] = {
			{Name = "G3-S1-Value1", Elements = {"Cat1", "Cat2", "Cat3"}},
			{Name = "G3-S2-Value2", Elements = {}},
			{Name = "G3-S3-Value3", Elements = {}}
		},
		["Sub2"] = {
			{Name = "G3-S1-Value1", Elements = {}},
			{Name = "G3-S2-Value2", Elements = {}},
			{Name = "G3-S3-Value3", Elements = {}}
		},
		["Sub3"] = {
			{Name = "Just One here", Elements = {}},
		},
	},
}

local masterOrder = {"General1", "General2", "General3"}
local subOrder = {"Sub1", "Sub2", "Sub3"}
local CatOrder = {"Cat1", "Cat2", "Cat3"}

local currentTable = masterTable
local tableHistory = {}
local Visible = false

function getOrderedKeys(tbl, orderReference)
	local orderedKeys = {}
	for key, _ in pairs(tbl) do
		table.insert(orderedKeys, key)
	end

	table.sort(orderedKeys, function(a, b)
		local indexA = table.find(orderReference, a) or math.huge
		local indexB = table.find(orderReference, b) or math.huge
		return indexA < indexB
	end)
	return orderedKeys
end

function assignButtonTexts(desiredTable)
	local index = 1

	if typeof(desiredTable) ~= "string" then
		local orderReference = masterOrder
	
		if currentTable ~= masterTable then
			
			if desiredTable[1] and desiredTable[1].Name then
				orderReference = nil 
			else
				orderReference = subOrder
			end
		end

	
		local isElementsTable = false
		for _, general in pairs(masterTable) do
			for _, sub in pairs(general) do
				for _, entry in ipairs(sub) do
					if desiredTable == entry.Elements then
						isElementsTable = true
						orderReference = CatOrder
						break
					end
				end
			end
		end

		if desiredTable[1] and desiredTable[1].Name then
		
			for i = 1, #desiredTable do
				local entry = desiredTable[i]
				local button = script.Parent:FindFirstChild(tostring(i))
				if button then
					button.Visible = true
					button.Text = entry.Name
					index = index + 1
				end
			end
		
			while true do
				local button = script.Parent:FindFirstChild(tostring(index))
				if not button then break end
				button.Visible = false
				index = index + 1
			end
		else
			
			local orderedKeys = getOrderedKeys(desiredTable, orderReference)
			for i, key in ipairs(orderedKeys) do
				local button = script.Parent:FindFirstChild(tostring(i))
				if button then
					button.Visible = true
					local value = desiredTable[key]
					if type(value) == "table" and not value.Name then
						button.Text = key 
					else
						button.Text = value 
					end
					index = index + 1
				end
			end
			
			while true do
				local button = script.Parent:FindFirstChild(tostring(index))
				if not button then break end
				button.Visible = false
				index = index + 1
			end
		end
	else
		print(desiredTable)
		currentTable = masterTable
		table.clear(tableHistory)
		assignButtonTexts(currentTable)
	end
end

assignButtonTexts(currentTable)

local validKeys = {Enum.KeyCode.One, Enum.KeyCode.Two, Enum.KeyCode.Three}
local ascociatedNumbers = {["Enum.KeyCode.One"] = 1, ["Enum.KeyCode.Two"] = 2, ["Enum.KeyCode.Three"] = 3}

UIS.InputBegan:Connect(function(input, gp)
	if gp then return end

	if input.KeyCode == Enum.KeyCode.T then
		Visible = not Visible
		script.Parent.Enabled = Visible

		if not Visible then
			currentTable = masterTable
			table.clear(tableHistory)
			assignButtonTexts(currentTable)
		end
	end

	if input.KeyCode == Enum.KeyCode.Backspace and #tableHistory > 0 then
		currentTable = table.remove(tableHistory)
		task.wait(0.1)
		assignButtonTexts(currentTable)
	end

	if not table.find(validKeys, input.KeyCode) then return end

	local key = ascociatedNumbers[tostring(input.KeyCode)]
	table.insert(tableHistory, currentTable)

	local orderReference = masterOrder
	if currentTable ~= masterTable then
		if currentTable[1] and currentTable[1].Name then
			orderReference = nil 
		else
			orderReference = subOrder
		end
	end

	if currentTable[1] and currentTable[1].Name then
		
		local selectedEntry = currentTable[key]
		if selectedEntry then
			currentTable = selectedEntry.Elements
			task.wait(0.1)
			assignButtonTexts(currentTable)
		end
	else
		
		local orderedKeys = getOrderedKeys(currentTable, orderReference)
		local selectedKey = orderedKeys[key]
		if selectedKey then
			currentTable = currentTable[selectedKey]
			task.wait(0.1)
			assignButtonTexts(currentTable)
		end
	end
end)
1 Like

The function is not able to return them as they are visually ordered in the code because using strings as an index, it means that it does not know the order in which you wrote it in the code.

Order is only implied when you are using tables like arrays, and listing them without explicit indexes.

Perhaps something like:

	["General3"] = {
		["Sub1"] = {
			[1] = {
				Name = "G3-S1-Value1",
				Values = {
					"Cat1",
					"Cat2",
					"Cat3"
				}
			},
			[2] = {Name = "G3-S1-Value2"},
			[3] = {Name = "G3-S1-Value3"},
		}
	}

image

Prints it in its original order.

How did you modify the rest of script to make it do that?

Hm? What do you mean by that?

Are you asking how I would modify the entire script to make it do that?

No just roblox does not ensure dictionary order so if it just happened so to print that way it doesn’t really mean anything

Yes you’re right.

My question though is that what are you really trying to achieve? Your title says that you want to keep the order of a dictionary, no?

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.