You canât preserve the âorder itâs written inâ with tables like this:
tbl = {
['Item1'] = 'a',
['Item2'] = 'b',
['Item3'] = 'c',
}
(This can come out in any order. This is called a dictionary. âItem1â, âItem2â, etc. are Keys.)
You can only preserve the âorder itâs written inâ with these types of tables:
tbl = {
[1] = 'a',
[2] = 'b',
[3] = 'c',
}
AKA
tbl = {'a', 'b', 'c'}
(This comes out in a defined order. This is called an array. 1
, 2
, etc. are Indexes.)
You have three ways around this:
- Store things in a dictionary (example 1), then create an array from it and sort it afterwards.
- Store things in a dictionary (example 1), then use LayoutOrder set to
Cost
to automatically show them in sorted order
- Store in an array (example 2)
You already get how to do 2 and 3. I figure Iâd chime in and explain how to do #1:
-- Step 1: Add 'Name' values to everything so that we know their names when in an array
for key, item in pairs(Knight) do
item.Name = key
end
-- Step 2: Make a sorted array
-- Step 2.1: Add everything to an array
local array = {}
for key, item in pairs(Knight) do
table.insert(array, item)
end
-- Step 2.2: Sort it
table.sort(array, function(a, b)
-- a and b are two items
-- we need to return if a is "smaller than" b
return a.Cost < b.Cost
end)
-- Now `array` is your items in correct order!
Some additional example snippets to help you learn sort functions
-- Sort by Cost, with largest first instead of smallest first:
table.sort(array, function(a, b)
return a.Cost > b.Cost
end)
-- Sort by name
table.sort(array, function(a, b)
return a.Name < b.Name
end)
-- Sort by Cost, and use infinity if it lacks a cost
table.sort(array, function(a, b)
local aCost = a.Cost
if aCost == nil then
aCost = math.huge
end
local bCost = b.Cost
if bCost == nil then
bCost = math.huge
end
return aCost < bCost
end)
-- More concise version:
table.sort(array, function(a, b)
return (a.Cost or math.huge) < (b.Cost or math.huge)
end)
-- Sort by Currency, giving each Currency a custom priority value
local CurrencyOrder = {
['Gems'] = 1,
['Gold'] = 2,
['Souls'] = 3,
}
table.sort(array, function(a, b)
return CurrencyOrder[a.Currency] < CurrencyOrder[b.Currency]
end)
-- Sort by Cost if the Currency is the same, or by Currency otherwise
-- This will group items together by currency
local CurrencyOrder = {
['Gems'] = 1,
['Gold'] = 2,
['Souls'] = 3,
}
table.sort(array, function(a, b)
if a.Currency ~= b.Currency then
return CurrencyOrder[a.Currency] < CurrencyOrder[b.Currency]
else
return (a.Cost or math.huge) < (b.Cost or math.huge)
end
end)
-- Sort by "Value", where each currency has a value multiplier on the cost
-- This will group items together by currency
local CurrencyValues = {
['Gold'] = 1,
['Gems'] = 2, -- worth 2x as much as gold
['Souls'] = 4, -- worth 4x as much as gold
}
table.sort(array, function(a, b)
local aMultiplier = CurrencyValues[a.Currency]
local aCost = a.Cost or math.huge
local aValue = aCost*aMultiplier
local bMultiplier = CurrencyValues[b.Currency]
local bCost = b.Cost or math.huge
local bValue = bCost*bMultiplier
return aValue < bValue
-- we could have condensed that into one line, but it would be a hard-to-read-mess!
end)
With this method, once you get it sorted, you can just use the index of each item in the array (aka i
) for the LayoutOrder.
If you just need something simple, then setting the LayoutOrder directly as qqtt991 suggested is smarter. If you need to group together items by currency or other complex logic, then using table sort functions can be very useful.