Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

String to table help

edited September 2013 in Questions Posts: 10

Im trying to serialize a table to a string, save in project data, then rebuild the table using the saved data when reset.
Ive serialized and saved but im not sure how to change it back, somesort of loop maybe?
Heres my example:

function setup()
    parameter.watch("a") parameter.watch("b")
 -- t = {{200,199},{933,188}}
    t = {}
    str = "{200,199},{933,188}"
    start = 1 -- en + 2 ? 11

    st = string.find(str,"{",start) -- start 
    cm = string.find(str,",",start) -- comma
    en = string.find(str,"}",start) -- end

    a = string.sub(str,st+1,cm-1)
    b = string.sub(str,cm+1,en-1)

    table.insert(t,{})
    table.insert(t[1],1,a)
    table.insert(t[1],2,b)

    print(t[1][1],t[1][2])
end
Tagged:

Comments

  • dave1707dave1707 Mod
    Posts: 7,903

    @JeffTheNoob If I understand what you're trying to do, maybe one of these will help. I took your string, pulled the numbers out of it and created 2 tables. Table t1 contains 1 number per entry. Table t2 contains 2 values per entry as vec2 values.


    function setup()     str = "{200,199},{933,188}"     t1={}     t2={}     c=1     for w in string.gmatch(str, "%d+") do         table.insert(t1,w)    -- t1 1 value per entry         if c==1 then             a=w             c=2         elseif c==2 then             table.insert(t2,vec2(a,w))   -- t2 2 values per entry                      c=1         end     end          print("\nvalues in table t1")     for a,b in pairs(t1) do         print(a,b)     end           print("\nvalues in table t2")     for a,b in pairs(t2) do         print(a,b)     end                     end
  • edited September 2013 Posts: 10

    @Dave1707 Yeah that works great, but if there's a decimal point it splits it into two values, is there a way around this, if not i can just floor the values and it will work fine.

    function setup()
        str = "{200,199},{933,188},{72.9,370}"
        t={}
        c=1
        for w in string.gmatch(str,"%d+") do
            if c==1 then
                a=w
                c=2
            elseif c==2 then
                table.insert(t,{})
                table.insert(t[#t],1,a)
                table.insert(t[#t],2,w)
                c=1
            end
        end
        for i = 1,#t do
            print(t[i][1],t[i][2])
        end
    end
    
  • edited September 2013 Posts: 1,976

    How about...

    tableStr = "{200, 199}, {933, 188}, {72.9, 370}"
    tbl = loadstring("return {" .. tableStr .. "}")()
    for k, v in ipairs(tbl) do
        print("Vector " .. k .. ", " .. tostring(v))
        print("X: " .. v[1])
        print("Y: " .. v[2])
        print("End of vector" .. k)
    end
    

    loadstring() can do all the hard work for you. Without printing, this is two lines of code.

  • dave1707dave1707 Mod
    edited September 2013 Posts: 7,903

    @JeffTheNoob Try this one. No exactly, but getting closer.

    function setup()
        str = "{200,199},{933,188},{72.9,370}"
        t={}
        c=1
        for w in string.gmatch(str,"%d+.%d+") do
            if c==1 then
                a=w
                c=2
            elseif c==2 then
                table.insert(t,{})
                table.insert(t[#t],1,a)
                table.insert(t[#t],2,w)
                c=1
            end
        end
        for i = 1,#t do
            print(t[i][1],t[i][2])
        end
    end
    
    
  • dave1707dave1707 Mod
    Posts: 7,903

    @JeffTheNoob I think this one will work


    function setup()     str = "{200,199},{933,188},{72.9,370}"     t={}     c=1     for w in string.gmatch(str,"%d+%.*%d+") do         if c==1 then             a=w             c=2         elseif c==2 then             table.insert(t,{})             table.insert(t[#t],1,a)             table.insert(t[#t],2,w)             c=1         end     end     for i = 1,#t do         print(t[i][1],t[i][2])     end end
  • @dave1707 Did you see mine?

  • dave1707dave1707 Mod
    Posts: 7,903

    @SkyTheCoder Yes, but I was determined to make it work with gmatch. I don't recall ever using loadstring, so I'm not sure how it works. I'll have to look into it because it never hurts to have different ways of doing something. Maybe I can use loadstring for something in the future.

  • edited September 2013 Posts: 1,976

    @dave1707 You call loadstring(string). string must be valid Lua, or the function returns nil. It returns a function that, when ran, executes the Lua code. If the code is something like return 0, the function loadstring() returns will itself return 0. That's how I used it to convert the valid Lua compressed table code into an actual table. I just added "return " before it. Also, as I said that loadstring() returns a function, that is why I have empty parenthesis after th function call, to execute the function retuned.

    You can make it work with gmatch if you want, but I think this is more efficient and in fewer lines. As payback for me teaching you something, you can tell me how gmatch works, because I have no idea. :P (Well, Briarfox taught me how to do one thing for the chat room, but still...)

  • dave1707dave1707 Mod
    Posts: 7,903

    @SkyTheCoder Sorry, but nothing you said above made any sense. I'll have to keep playing around with it. As for gmatch, that's a string parser and based on the pattern you use, you can pull just about anything from a string. The only problem is, it's really complicated trying to set up the pattern, for me anyways. It's mostly hit and miss right now. It would take a lot of typing if I tried to teach you about it. The easiest is looking in the Lua manual.

  • IgnatzIgnatz Mod
    Posts: 5,396

    @SkyTheCoder - to learn gmatch, maybe have a look at some regex tutorials (gmatch is a cut down version of regex). I learned something about regex last year, and what helped me a lot was when you are trying to understand a pattern, break it into bits and translate them one by one. You'll find there are relatively few pattern elements that get used a lot, so you can get the hang of it fairly quickly.

  • dave1707dave1707 Mod
    Posts: 7,903

    @SkyTheCoder I guess I don't understand how loadstring seperated the string into individual
    numbers. At least with gmatch, I can see what I'm trying to do using the pattern. With loadstring, I don't see what's doing the work.

  • edited September 2013 Posts: 580

    @dave1707: loadstring compiles a string into a function. @SkyTheCoder is using it to compile and create a function that returns a table (built from the string of (valid) Lua code he puts together) which he then calls, assigning the result to the variable 'tbl'. His code is actually more complex than it needs to be due to unnecessarily concatenating his strings. He could have just done:

    tbl = loadstring("return { {200, 199}, {933, 188}, {72.9, 370} }")()
    

    It's a nice trick, and will work, but it is kind of a cheat ;) Since Codea allows loadstring it's fine, but not necessarily the best practice in other Lua environments because they may be sandboxed to disallow loadstring. I always prefer another solution if I can find one (like gmatch in this case).

  • @toadkick I separated the strings and concatenated them to show you could use any compressed table you wanted in it.

    I don't really see myself using any other Lua IDE. If it's okay in Codea, it's okay with me. :P

  • Thanks for the help everyone.@dave1707 the last gmatch pattern seems to ignore values under 10 and the - on negative values. Gmatch patterns look confusing so i went for loadstring. Heres my test project:

    function setup()
        parameter.action("Save",function()savetable(e,"eString")savetable(col,"colString")end)
        parameter.action("Clear",function()clearProjectData()end)
        parameter.action("Restart",function()restart()end)
    
        if readProjectData("eString") ~= nil then
            e = loadstring(readProjectData("eString"))()
        else
            e = {}
        end
        if readProjectData("colString") ~= nil then
            col = loadstring(readProjectData("colString"))()
        else
            col = {}
        end
    end
    
    function savetable(tab,key) -- (table to string,key for saved string)
        local s = {"return {"}
        for i=1,#tab do
            s[#s+1] = "{"
            for j=1,#tab[i] do
                s[#s+1] = tab[i][j]
                if j ~= #tab[i] then
                    s[#s+1] = ","
                end
            end
            if i ~= #tab then
                s[#s+1] = "},"
            else
                s[#s+1] = "}"
            end
        end
        s[#s+1] = "}"
        tab.str = table.concat(s)
        print(tab.str)
        saveProjectData(key,tab.str)
        s = nil
    end
    
    function draw()
        background()
        for i = 1,#e do
            fill(col[i][1],col[i][2],col[i][3],col[i][4])
            ellipse(e[i][1],e[i][2],e[i][3])
        end
    end
    
    function touched(touch)
        local c = CurrentTouch
        if c.state == ENDED then
            table.insert(e,#e+1,{c.x})
            table.insert(e[#e],2,c.y)
            table.insert(e[#e],3,math.random(20,200))
            table.insert(col,#col+1,{math.random(0,255)})
            table.insert(col[#col],2,math.random(0,255))
            table.insert(col[#col],3,math.random(0,255))
            table.insert(col[#col],4,math.random(100,230))
        end
    end
    
  • dave1707dave1707 Mod
    edited September 2013 Posts: 7,903

    @JeffTheNoob That's the trouble with using patterns. You have to know exactly what you're looking for. Each time I gave you a pattern that worked for the string you gave me, you changed what I was looking for. Since you can use @SkyTheCoder routine, that's all that matters. Using patterns is very specific and powerful, but you need to know everything your trying to match to create the correct pattern. I'm still learning that. The pattern below works for everything so far, I think.


    function setup()     str = "{200,199},{933,188},{72.9,370},{3.5,-2}"     t={}     c=1     for w in string.gmatch(str,"[+-]*%d*%.*%d+") do         if c==1 then             a=w             c=2         elseif c==2 then             table.insert(t,{})             table.insert(t[#t],1,a)             table.insert(t[#t],2,w)             c=1         end     end     for i = 1,#t do         print(t[i][1],t[i][2])     end end
Sign In or Register to comment.