Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

How do I compress tables?

Asked by
GShocked 150
9 years ago

Let's say I have a JSONEncoded table that looks like this:

l = "[24,24,24,24,24,55,12,12,56,87,87,87,87,92]"

I want to turn it into something like this:

l = "[24.5,55,12.2,56,87.4,92]"

So the . is really an exponent symbol ^.

I've already tried my hand at this, and it somewhat worked. The problem is that it mixes parts my table up. Here is my script so far (although it uses a model's children for the table, not a JSONEncoded table). A script that formats JSONEncoded tables or a model's children would be helpful.

ImgScript = {} --The main holder for all of the color values
Temp = {} --The temporary holder for color values. This is so we can collect the '4, 4, 4' and turn it into '4^3'. Due to JSON limitations, the ^ has to be replaced with a . So when you see 4.3, remember it means 4, 4, 4!
for index, child in pairs(workspace.IMG:GetChildren()) do
    n = child.BrickColor.Number
    if n == Temp[1] then
        Temp[2] = Temp[2] + 1
    else
        if #Temp == 0 then
            table.insert(Temp, n)
            table.insert(Temp, 1)
        else
            table.insert(ImgScript, Temp[1] .. '.' .. Temp[2])
            Temp = {}
            table.insert(Temp, n)
            table.insert(Temp, 1)
        end
    end
end
1
Is the order of the list significant? BlueTaslem 18071 — 9y
1
You are going through the table in pairs. This does not specifically iterate over every index in order. Have you tried ipairs? randomsmileyface 375 — 9y
0
@BlueTaslem Yes the order of the list is significant GShocked 150 — 9y
0
@randomsmileyface Changing pairs to ipairs didn't change the output. The numbers are still out of order, although the exponents are right. GShocked 150 — 9y

2 answers

Log in to vote
2
Answered by 9 years ago

You're looking at something similar to RLE.

local parsed = {};
local last,le = '',0
jsonTable:sub(2,-2):gsub('[^,]+',function(c) le=le+1 
if last ~= c then
 if  le == 1 then
 parsed[#parsed+1] = last
 else
 parsed[#parsed+1] = last..'.'..le 
end
 last = c; le = 0 end 
end)
parsed = '['..table.concat(parsed,',')..']'

Parsed is now your compressed table. If you need things explaining I'll do it later because I'm not at a computer and it's tricky typing here. I'll also sort out my code formatting when I get on a computer.

0
Thanks, this somewhat solved my answer. The output isn't disorganized like the output of my script, so that is a +1. The end and beginning of the output are a little funky though, being `[,[24,24.4,55,12.2,56,87.4]` GShocked 150 — 9y
1
Ah that was my bad. I forgot to strip the [] from the JSONTABLE. I've edited my answer to try and solve this. User#6546 35 — 9y
Ad
Log in to vote
0
Answered by
BlueTaslem 18071 Moderation Voter Administrator Community Moderator Super Administrator
9 years ago

The term for this is run-length encoding, because you write the length (number of things) in a "run" (same thing over and over).

If you have an actual table input, and you want to make an actual table, output, code to do this might look like this:

local output = {}

for i = 1, #input do
    if input[i] ~= input[i-1] then
        -- Start of a new run!
        local len = {}
        for j = i, #input do
        -- Figure out how long the run is
            if input[i] ~= input[j] then
                len = j - i
                break
            end
        end
        -- Record the run (even if it's length 1)
        table.insert(output, {value = input[i], run = len})
    end
end

Without peeking-ahead like the above, you could write it like this:

local output = {}

local last = input[1]
local run = 1
for i = 2, #input+1 do -- +1 to deal with the last run
    if input[i] ~= last then
        table.insert(output, {value = last, run = run})
    else
        run = run + 1
    end
end

Answer this question