Tables are driving me crazy, using multiple table entries

OK, the one thing with Lua that I continually struggle with is tables. I just can’t get my head around some of it.

I understand the basic table entries, it’s trying to nest them (like a database almost!)

For the love of _insert deity_ please help me understand this :slight_smile:

For what it’s worth, I have pored over the tutorials @ coronalabs numerous times, I’ve read lua.orgs entries, I’ve read the grid entries on a post but I just don’t get it!

I am trying to work a grid. for each entry on the grid, I’d like to have more than one value available.

For example:   X, Y,  then Sprite, value

For grid 1, it holds sprite “dog” and has a value of 6. For grid 2 it has sprite “apple” and 4

From there, I’d like to be able to retrieve those values based on the grid (X,Y)

Here’s what I put together to test with…

It sets up the tables with the map data, and a little loop at the bottom prints out the table like the map.

I half (hope) suspect I’m most of the way there, I’m just not seeing it though.

-- working with tables local grid = {} gridsizex = 32 -- Grid is 32 x 20 gridsizey = 20 -- Grid is 32 x 20 -- Mapdata is hardcoded for now. local mapdata = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,7,1,1,1,1,5,5,5,1,1,1,1,1,1,8,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,6,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,9,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,5,5,5,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} -- For each row (20) for mapy=1,gridsizey do -- Pretty sure this is wrong, I suspect the table declaration should be elsewhere grid[mapy] = {} end local idx = 1 for mapy=1,gridsizey do for mapx=1,gridsizex do grid[mapy][mapx] = mapdata[idx] -- 'I know this is incorrect, just trying to get the point across' -- if mapdata[idx] == 1 then -- grid[idx]["sprite"] = spr\_ground -- grid[idx]["value"] = 10 -- end -- -- if mapdata[idx] == 5 then -- grid[idx]["sprite"] = spr\_water -- grid[idx]["value"] = 15 -- end idx=idx + 1 end end -- For the X/Y grid, I want to be able to retrieve a sprite and value entry. -- print(grid[x][y][sprite]) -- print(grid[x][y][value]) print( "Printing Map" ) px="" for mapy=1,gridsizey do for mapx=1,gridsizex do px = px..grid[mapy][mapx] end print (px) px="" end

Graham,

Hope this helps.  I kept as much of your original code in tact as I could. There are a lot of ways to do what you are trying to do, but this way kept most of your code in tact and will work, for what you asked.

I did ‘format’ the first 4 rows of your mapdata table to be easier to read. spacing out the values in groups of 5 (or 2) and grouped them into rows of 32… to match the dimensions of your grid. You can do the rest of the rows that way, if you so desire. Of course as you can see, it makes no difference to the code, it just makes it easier to read and possibly debug any of the elements of that table that represents a grid. If a single dimension table like yours is representing a grid, I like to format the values to match the dimensions of the grid … in your case, 20 rows of 32 values.  But, it is up to you.

I changed the code where you had 2 ‘if-then blocks’ to a ‘if-elseif-else block’.  The else will catch any value not 1 or 5. You will need to add an ‘elseif’ for the ‘7’ and ‘8’ values I saw in your table.  The else (to catch any value not in the ‘else if block’ is up to you.It is not really needed as long as you have an else-elseif for any value you have in the mapdata table.

the x and y for each table is computed using  40x40 size cels for the grid.  You obviously can change those values as well as the start values xpos and ypos to whatever you want.

local mapdata = {1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1, 1,1,1,1,1, 1,1,1,1,1, 7,1,1,1,1, 5,5,5,1,1, 1,1,1,1,8, 1,1,1,1,1, 1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1, 1,1, 1,1,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,5,5,5,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,5, 5,5,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,5,5,5,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,5, 5,5,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,6,1, 1,1,1,1,1, 1,5,5,5,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,1,1,1,1, 1,1,1,9,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1} local grid = {} local gridsizex = 32 -- Grid is 32 x 20 local gridsizey = 20 -- Grid is 32 x 20 local xpos = 20 local ypos= 20 local cellSizeWt = 40 local cellSizeHt = 40 local idx = 1 for mapy=1,gridsizey do table.insert(grid, {}) for mapx=1,gridsizex do if mapdata[idx] == 1 then grid[mapy][mapx] = { x = xpos, y = ypos, sprite = "spr\_ground", value = 10 } elseif mapdata[idx] == 5 then grid[mapy][mapx] = { x = xpos, y = ypos, sprite = "spr\_water", value = 15 } else grid[mapy][mapx] = { x = xpos, y = ypos, sprite = "other", value = 1 } end xpos = xpos + cellSizeWt idx=idx + 1 end xpos = 20 ypos = ypos + cellSizeHt end print(grid[1][1].sprite , grid[1][1].value ) print(grid[3][8].sprite , grid[3][8].value) for i = 1, #grid do for ii = 1, #grid[i] do print(grid[i][ii].sprite) end print(" ") end print( "Printing Map" ) px="" for mapy=1,gridsizey do for mapx=1,gridsizex do px = px .. " : " ..grid[mapy][mapx].x end print (px) px="" end  

Bob

Just to help with the understanding of arrays/tables in Lua…

First, there are no such thing as two dimensional arrays. Lua uses an array of arrays.

local grid = {} -- construct a single dimensional array for y = 1, gridSizeY do     grid[y] = {} -- make an array inside each array row end

At this point, you have a single dimensional array of empty arrays. These are your grid rows. Now to make the columns.

local grid = {} -- construct a single dimensional array for y = 1, gridSizeY do grid[y] = {} -- make an array inside each array row for x = 1, gridSizeX do grid[y] = {} -- make the column end end

Now you have a structure that you can access as:   grid[y][x]

Many programmers however will not use a 2D array structure like this. Instead it’s really easy to calculate an offset into a single dimension array. In your original mapData example:

mapData[(y - 1) * gridsizey + (x - 1)]

Of course this works best when you think of things as 0 offset instead of 1 offset like Lua.

Bob,

Thank you for the concise answer, well put together. Obviously this process works, but I wanted to take a minute to understand it instead of just running with it :slight_smile:

I think the key is this line… 

            grid[mapy][mapx] = { x = xpos, y = ypos, sprite = “spr_ground”, value = 10 }

As demonstrated by Rob, I believe the creation of mapy & mapx was OK, this appears to be the missing link :slight_smile:

So, here you have taken the two entries of X/Y (Eg: grid [1] [1] and given it another table entry, this time defining the indexes (xpos,ypos, sprite and value) Robs other point I think I’ve seen elsewhere, but I find it easier to get my head around the old style :slight_smile:

It does make sense, but I’ll confess that for me it’s only just :slight_smile:  

Many thanks to you both for your input. Extra kudos to you Bob for taking the time to rewrite that section and defining it so well.

Thanks folks.

Graham,

Hope this helps.  I kept as much of your original code in tact as I could. There are a lot of ways to do what you are trying to do, but this way kept most of your code in tact and will work, for what you asked.

I did ‘format’ the first 4 rows of your mapdata table to be easier to read. spacing out the values in groups of 5 (or 2) and grouped them into rows of 32… to match the dimensions of your grid. You can do the rest of the rows that way, if you so desire. Of course as you can see, it makes no difference to the code, it just makes it easier to read and possibly debug any of the elements of that table that represents a grid. If a single dimension table like yours is representing a grid, I like to format the values to match the dimensions of the grid … in your case, 20 rows of 32 values.  But, it is up to you.

I changed the code where you had 2 ‘if-then blocks’ to a ‘if-elseif-else block’.  The else will catch any value not 1 or 5. You will need to add an ‘elseif’ for the ‘7’ and ‘8’ values I saw in your table.  The else (to catch any value not in the ‘else if block’ is up to you.It is not really needed as long as you have an else-elseif for any value you have in the mapdata table.

the x and y for each table is computed using  40x40 size cels for the grid.  You obviously can change those values as well as the start values xpos and ypos to whatever you want.

local mapdata = {1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1, 1,1,1,1,1, 1,1,1,1,1, 7,1,1,1,1, 5,5,5,1,1, 1,1,1,1,8, 1,1,1,1,1, 1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1, 1,1, 1,1,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,5,5,5,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,5, 5,5,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,5,5,5,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,5,5,5,5, 5,5,5,5,5, 5,5,5,5,5, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,5, 5,5,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,6,1, 1,1,1,1,1, 1,5,5,5,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,5,5, 5,1,1,1,1, 1,1,1,9,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 5,5,5,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1} local grid = {} local gridsizex = 32 -- Grid is 32 x 20 local gridsizey = 20 -- Grid is 32 x 20 local xpos = 20 local ypos= 20 local cellSizeWt = 40 local cellSizeHt = 40 local idx = 1 for mapy=1,gridsizey do table.insert(grid, {}) for mapx=1,gridsizex do if mapdata[idx] == 1 then grid[mapy][mapx] = { x = xpos, y = ypos, sprite = "spr\_ground", value = 10 } elseif mapdata[idx] == 5 then grid[mapy][mapx] = { x = xpos, y = ypos, sprite = "spr\_water", value = 15 } else grid[mapy][mapx] = { x = xpos, y = ypos, sprite = "other", value = 1 } end xpos = xpos + cellSizeWt idx=idx + 1 end xpos = 20 ypos = ypos + cellSizeHt end print(grid[1][1].sprite , grid[1][1].value ) print(grid[3][8].sprite , grid[3][8].value) for i = 1, #grid do for ii = 1, #grid[i] do print(grid[i][ii].sprite) end print(" ") end print( "Printing Map" ) px="" for mapy=1,gridsizey do for mapx=1,gridsizex do px = px .. " : " ..grid[mapy][mapx].x end print (px) px="" end  

Bob

Just to help with the understanding of arrays/tables in Lua…

First, there are no such thing as two dimensional arrays. Lua uses an array of arrays.

local grid = {} -- construct a single dimensional array for y = 1, gridSizeY do     grid[y] = {} -- make an array inside each array row end

At this point, you have a single dimensional array of empty arrays. These are your grid rows. Now to make the columns.

local grid = {} -- construct a single dimensional array for y = 1, gridSizeY do grid[y] = {} -- make an array inside each array row for x = 1, gridSizeX do grid[y] = {} -- make the column end end

Now you have a structure that you can access as:   grid[y][x]

Many programmers however will not use a 2D array structure like this. Instead it’s really easy to calculate an offset into a single dimension array. In your original mapData example:

mapData[(y - 1) * gridsizey + (x - 1)]

Of course this works best when you think of things as 0 offset instead of 1 offset like Lua.

Bob,

Thank you for the concise answer, well put together. Obviously this process works, but I wanted to take a minute to understand it instead of just running with it :slight_smile:

I think the key is this line… 

            grid[mapy][mapx] = { x = xpos, y = ypos, sprite = “spr_ground”, value = 10 }

As demonstrated by Rob, I believe the creation of mapy & mapx was OK, this appears to be the missing link :slight_smile:

So, here you have taken the two entries of X/Y (Eg: grid [1] [1] and given it another table entry, this time defining the indexes (xpos,ypos, sprite and value) Robs other point I think I’ve seen elsewhere, but I find it easier to get my head around the old style :slight_smile:

It does make sense, but I’ll confess that for me it’s only just :slight_smile:  

Many thanks to you both for your input. Extra kudos to you Bob for taking the time to rewrite that section and defining it so well.

Thanks folks.