Table help?

I have a table which includes various subtables.
This is some (pretty lazy) code I’m just using to test (because I’m too stupid to think of a better alternative):



for _, v in pairs( drawtable ) do
	for tblnum, tbl in pairs( v ) do
		print(tostring(_).." "..tostring(tblnum).." "..tostring(tbl).." ")
	end
end


As you can see, the table is called ‘drawtable’, and has some subtables which I need values of. This prints something like



1 m gui/center_gradient
1 x 181 
1 c 0 0 0 255 
1 r 0 
1 y 27 
1 sa 50 
1 dt default 
1 su 50 


Into the console. However, instead of a ‘1’ being at the start of everything, I’d like the table to be as compact as possible (when printed) as I’m going to need to save it with a lot of the same kind of data to get read and interpreted later.
I’d like it to look like



{m gui/center_gradient
x 181 
c 0 0 0 255 
r 0 
y 27 
sa 50 
dt default 
su 50}


Instead, but I’m too stupid to think of a solution. Please help. Also, how would I make this new data only print on a single line, like



{m gui/center_gradient x 181 c 0 0 0 255 r 0 y 27 sa 50 dt default su 50}


just get rid of tostring(_)? what are you saving it for? depending on what you’re doing you might want to use json

JSON is too large for what I’m doing. Also, getting rid of tostring(_) wouldn’t cause brackets to appear at the front and back of the data.

What are you trying to do, exactly? You’re not trying to serialize data by copypasting from console into Notepad, are you?

I’m working on a MS Paint replica.



{m gui/center_gradient //The material of the brush
x 181 //The position of the cursor on the X axis when the brush was drawn
c 0 0 0 255 //The color of the brush
r 0 //The rotation of the brush
y 27 //The position of the cursor on the Y axis when the brush was drawn
sa 50 //The size across (the width)
dt default //The draw type. This is very important, as different types (such as lines) need different code to work.
su 50} //The size upwards (the height)


The problem with all that is how often the brush will get drawn (for every splotch on the paper), and I don’t want to resort to 100% surface.DrawLine. That’s why I want to simplify all this so it can be easily read by the for k, v in pairs loop that feeds all the parts of the table into a surface.DrawTexturedRectRotated, which gets called whenever the vgui this gets put on is called to get painted.

[editline]26th April 2015[/editline]

I did the one-lined-with-brackets part of this, but I still have no idea how I’m going to compress it from here. Probably just a string.Replace…



local stringbuildup = ""

for _, v in pairs( drawtable ) do
	stringbuildup = stringbuildup.."{"
		for tblnum, tbl in pairs( v ) do
			stringbuildup = stringbuildup.." "..tostring(tblnum).." "..tostring(tbl)
		end
	stringbuildup = stringbuildup.." }"
end

print(stringbuildup)


I have to be doing something extremely wrong here, nobody does this for something like compression.

[editline]26th April 2015[/editline]

Less confusing example- If I wanted to remove the number ‘255’ from
{m gui/center_gradient x 181 c 0 0 0 255 r 0 y 27 sa 50 dt default su 50
What would I do, if ‘c’ is a marker for the 3 digits that will always have a space between them?

Your English… You’ve just posted more confusing example.
alpha for Color by default is 255. Why would you remove 255?
Why would you compress string?



output = output:gsub("
", "") -- Replaces all new-line characters from output with empty string, and saves a new string into "output".

[editline]26th April 2015[/editline]

Solution: https://gist.github.com/OmegaExtern/26129e6fc80b333dc46e#file-table_help-lua


-- Solution for: http://forum.facepunch.com/showthread.php?t=1462506&p=47602760&viewfull=1#post47602760
local getinfo, getlocal, gsub = debug.getinfo, debug.getlocal, string.gsub
string.Interp = function(str, tbl)
    local funcname = getinfo(1.0, "n").name
    for argc = 1.0, getinfo(1.0).nparams, 1.0 do
        local argname = getlocal(1.0, argc)
        -- Hard-coded with <3 by OmegaExtern.
        if argc == 1.0 and argname == "str" then
            assert(type(str) == "string" and isstring(str), Format("bad argument #%i (%s) to '%s' (string expected, got %s)", argc, argname, funcname, type(str)))
        elseif argc == 2.0 and argname == "tbl" then
            assert(type(tbl) == "table" and istable(tbl), Format("bad argument #%i (%s) to '%s' (table expected, got %s)", argc, argname, funcname, type(tbl)))
        else
            error("nope.")
        end
    end
    return gsub(str, "{(%w+)}", tbl)
end
local out = Format("{%s}", string.Interp("m {m} x {x} c {cr} {cg} {cb} r {r} y {y} sa {sa} dt {dt} su {su}",
                                            {
                                                m = "gui/center_gradient",
                                                x = 181.0,
                                                cr = 0.0,
                                                cg = 0.0,
                                                cb = 0.0,
                                                r = 0.0,
                                                y = 27.0,
                                                sa = 50.0,
                                                dt = "default",
                                                su = 50.0
                                            } -- Input your (valid) "drawtable" table here.
                                        )
                  )
print(out) --Outputs:{m gui/center_gradient x 181 c 0 0 0 r 0 y 27 sa 50 dt default su 50}

I want a short string because the user has an option to save their ‘painting’ (meaning a text file containing the string), which will then be able to get read and put back into a table. By taking away the 255 from the color table (meaning the alpha, yes, I know), I will be adding it back again later anyway (as it won’t change from 255) by doing tonumber() on the number strings sourced from the text file when it gets opened again and loaded. It needs to be very short as paint splotches will be constantly made (i.e. added to the table which gets cycled through to get drawn), and so if I use a massive table such as the one shown in the example, there will be something like a 10GB text file for one painting.

So, it is not about table? Instead you are looking for compressing a string?

Check these functions:

util.Compress(string)

util.Decompress(string)
This uses FastLZ algorithm. See benchmark results here.
To put it simple, call util.Compress function and pass in your “massive” string in before saving it to the text file (file.Write).
“1 billion bytes” … 1GB … " => 470MB within 18.2s"-FastLZ.


When you need to “parse” the text file to draw the picture, call util.Decompress and pass in a string that you have saved into the text file (file.Read).
It is not efficient for “tiny” length.
Or write your own compression library.
See updated gist here.

Thanks for that! Surprised I didn’t know that before. Wait, I found a problem…

The ‘drawtable’ table consists of many subtables, one for every brush splotch. Every one of these subtables includes a Color() table, probably called a sub-subtable. It seems by doing TableToJSON() that the sub-subtable of the Color value doesn’t get saved at all! How would I work around this?

If you’re looking for a really really fast table encoder:
https://github.com/SuperiorServers/plib_v2/blob/master/lua/includes/modules/pon2.lua

I’d like to add a disclaimer that this library is not yet released as a stand alone, is subject to development changes, and is not the final version.

The output is not human readable but it is very very compact and it’s faster than anything else i’ve benchmarked it against

see lua/benchmarks in the git repo.

if you want something more human readable see
https://github.com/SuperiorServers/plib_v2/blob/master/lua/includes/modules/pon1.lua
which I believe still benchmarks faster than von

benchmarks:



Serializer: pon v2 dev
	Data Set: entity array
		encode: 0.16339667740993 (0.011529309775881)
		decode: 0.097343547184522 (0.0051987991934084)
	Data Set: float array
		encode: 0.20472723329593 (0.02337340600991)
		decode: 0.10665912192408 (0.018584092264945)
	Data Set: Assoc String Array
		encode: 0.067560130205237 (0)
		decode: 0.040857060935025 (0)
	Data Set: int array
		encode: 0.1837446845077 (0)
		decode: 0.16558527629456 (0.046761718342481)
	Data Set: Vector array
		encode: 0.50228695138523 (0)
		decode: 0.29842749988529 (0.010797146286876)
	Data Set: Assoc Number Array
		encode: 0.14638739427838 (0.018338868645202)
		decode: 0.088943396016845 (0.0030800554281427)
	Data Set: string array
		encode: 0.052941412014547 (0.0070568284548358)
		decode: 0.029574143902124 (0)


Serializer: pon
	Data Set: entity array
		encode: 0.51766267693586 (0.3657953093018)
		decode: 0.19702271051307 (0.10487796252195)
	Data Set: float array
		encode: 0.18135382728602 (0)
		decode: 0.088075029659137 (0)
	Data Set: Assoc String Array
		encode: 0.10312836944999 (0.035568239244753)
		decode: 0.051538464011628 (0.010681403076603)
	Data Set: int array
		encode: 0.18875174747402 (0.0050070629663139)
		decode: 0.11882355795208 (0)
	Data Set: Vector array
		encode: 0.60329160829576 (0.10100465691053)
		decode: 0.52640479667923 (0.23877444308081)
	Data Set: Assoc Number Array
		encode: 0.12804852563318 (0)
		decode: 0.085863340588702 (0)
	Data Set: string array
		encode: 0.12765043913734 (0.081765855577629)
		decode: 0.030723392141198 (0.0011492482390736)


Serializer: von
	Data Set: entity array
		encode: 0.46608095536081 (0.31421358772675)
		decode: 0.19472713684323 (0.10258238885211)
	Data Set: float array
		encode: 0.20189006324082 (0.020536235954808)
		decode: 0.15986154072337 (0.071786511064232)
	Data Set: Assoc String Array
		encode: 0.11796542142366 (0.050405291218425)
		decode: 0.11163812593037 (0.070781064995344)
	Data Set: int array
		encode: 0.46019295796094 (0.27644827345324)
		decode: 0.21966629128065 (0.10084273332856)
	Data Set: Vector array
		encode: 0.61394436785062 (0.11165741646539)
		decode: 0.31506178670693 (0.027431433108518)
	Data Set: Assoc Number Array
		encode: 0.20127656577031 (0.073228040137138)
		decode: 0.15695539239141 (0.071092051802708)
	Data Set: string array
		encode: 0.13466225634372 (0.088777672784005)


I don’t really care about encoders right now, although thanks for informing me about another possibility. I just want to get TableToJSON to work the way I want (as described in my last post).

What I decided to do (by the way) was convert the table to JSON, then encode it, and then save it.