Sorting and Generating a Business Menu by Category (Alphabetically)

I’m having a bit of trouble getting a table (in Tiramisu), filled with item data, to sort by it’s category (in alphabetical order). I’m still fairly new to LUA and programming in general, so I’m not sure if I’m going about it the right way.

The snippet that builds the business menu item data looks like this:

business.lua

[lua]
CAKE.Business = {}

–Copies all buyable items on the CAKE.Business table.
function CAKE.BuildItemGroups()
local tbl = {}
for k,v in pairs(CAKE.ItemData) do
if !CAKE.Business[v.ItemGroup] then CAKE.Business[v.ItemGroup] = {} end
if v.Purchaseable then
tbl = {}
tbl.Class = v.Class
tbl.Model = v.Model
tbl.Name = v.Name
tbl.Description = v.Description … "
Price: " … v.Price
tbl.Price = v.Price
tbl.category = v.category
tbl.IconM = v.IconM

		--Category Sort
		table.sort(tbl, function(a,b) 
			return a.category > b.category 
		end)
		
		--Test the results
		 for k,v in pairs(tbl) do 
		 print(k, v) 
		 end
		
		table.insert(CAKE.Business[v.ItemGroup], tbl)
	end
end

end
[/lua]

I’ve tried sorting the “tbl” table by category, and even the CAKE.Business menu by category, but both don’t seem to sort when I do that. I haven’t been getting any errors, but the item order doesn’t go alphabetical. I’ve also double-checked to make sure the category key is working, and it is. It even shows up on the item tooltip via this:

cl_inventory.lua
[lua]
–Sets an item to be used on the inventory slot. The item thing is a table, not a string. Amount defaults to 1.
function PANEL:SetItem( item, amount )
self.Item = item

if !self.Icon then
	self.Icon = vgui.Create( "InventorySlot_Icon", self )
	self:SetIconSize( self.IconSize )
end
-- Item tooltip. Added item.category.
if item.Description != "" then self:SetToolTip( "[" .. item.category .. "]" .. "

" … item.Name … "
" … item.Description )
else self:SetToolTip( “[” … item.category … “]” … "
" … item.Name ) end
– Changes the Icon model to the “IconM” field if valid.
if item.IconM == “” then self.Icon:SetModel( item.Model )
else self.Icon:SetModel( item.IconM ) end

self:SetAmount( amount or 1 )
self:OnUseItem( item, amount )

end
[/lua]

The business menu actually builds the icons in this little snippet of code:

cl_business.lua
[lua]
local icontable = {}

for k, item in pairs( BusinessTable[buygroup] ) do
icontable[k] = vgui.Create( “InventorySlot” )
icontable[k]:SetIconSize( 48 )
icontable[k]:SetItem( item )
icontable[k]:DisableDrag()
icontable[k].OnMousePressed = function()
icontable[k]:OpenMenu()
end
icontable[k].OnMouseReleased = function() end
icontable[k].OpenMenu = function()
local ContextMenu = DermaMenu()
ContextMenu:AddOption(“Buy”, function() LocalPlayer():ConCommand("rp_buyitem " … icontable[k]:GetItem().Class ) end)
ContextMenu:Open()
end
icontable[k].PaintOver = function()
surface.SetTextColor(Color(255,255,255,255));
surface.SetFont(“TirimisuTabsFont”);
surface.SetTextPos( icontable[k]:GetWide() - 20, icontable[k]:GetTall() - 14);
surface.DrawText( icontable[k]:GetItem().Price or “0” )
end
grid:AddItem( icontable[k] )
end
end
end
[/lua]

So, I’m not sure if I’ve been going about this the right way, but I figured that sorting the table in the business.lua file would work, as then the code pulls that data and builds everything else. It doesn’t seem to be working though, as the print output to the console isn’t in alphabetical order (by category). It’ll show zipties as first (category: Miscellaneous), then an Alcohol item, then some Weaponry, followed by random mixtures of other items. Also, any changes to how the sorting function compares the a.category and b.category just shifts the items around in a weird way.

Any ideas on how to get this to work would be appreciated.

**[G.SortedPairs

http://wiki.garrysmod.com/favicon.ico](http://wiki.garrysmod.com/?title=G.SortedPairs)**

Sorts through a table’s keys from lowest to highest, starting with numbers.

**[G.SortedPairsByValue

http://wiki.garrysmod.com/favicon.ico](http://wiki.garrysmod.com/?title=G.SortedPairsByValue)**

This goes by value of the key.

**[G.SortedPairsByMemberValue

http://wiki.garrysmod.com/favicon.ico](http://wiki.garrysmod.com/?title=G.SortedPairsByMemberValue)**

This goes by member of a table. Syntax is SortedPairsByMemberValue(table,member)

Unfortunately, that’s giving me an error:

[lua]
for k, v in SortedPairsByMemberValue(tbl, “category”) do
print(k, v.category)
end
[/lua]

[lua] Hook ‘TiramisuBuildItemGroups’ Failed: [lua\includes\extensions able.lua:478] attempt to index local ‘v’ (a string value)[/lua]

Here’s the hook (it just calls the CAKE.BuildItemGroups() function I’ve been messing with):

[lua]hook.Add( “InitPostEntity”, “TiramisuBuildItemGroups”, function()
CAKE.BuildItemGroups()
end)[/lua]

Line 478 of table.lua is v.__key = k in this:

[lua]

---------------------------------------------------------
Name: table.ClearKeys( table, bSaveKey )
Desc: Clears the keys, converting to a numbered format
---------------------------------------------------------
/
function table.ClearKeys( Table, bSaveKey )

local OutTable = {}

for k, v in pairs( Table ) do
	if ( bSaveKey ) then
		v.__key = k
	end
	table.insert( OutTable, v )	
end

return OutTable

end
[/lua]

SortedPairsByMemberValue calls table.ClearKeys:

[lua]
/*---------------------------------------------------------
A Pairs function

	Sorted by Member Value (All table entries must be a table!)

---------------------------------------------------------*/
function SortedPairsByMemberValue( pTable, pValueName, Desc )

Desc = Desc or false

local pSortedTable = table.ClearKeys( pTable, true )

table.SortByMember( pSortedTable, pValueName, !Desc )

local SortedIndex = {}
for k, v in ipairs( pSortedTable ) do
	table.insert( SortedIndex, v.__key )
end

pTable.__SortedIndex = SortedIndex

return fnPairsSorted, pTable, nil

end
[/lua]

Maybe I shouldn’t bother with trying to organize the table right here, but rather when the function generates the icons?