#### 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 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:

• 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

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.

• 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

• 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
• Posts: 1,976

@dave1707 Did you see mine?

• 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...)

• 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.

• 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.

• 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).

• Posts: 1,976

@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

• Posts: 10

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)

else
e = {}
end
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

• 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