Lua Acessing table values within nested table - lua

I'm trying to test certain variables on a grid made out of nested tables. However no matter what I try it wont give me the values stored within the variables only the data type or a nil value
y = {}
for _y = 0,16 do
for _x = 0,16 do
x = {}
x.x = _x
x.y = _y
x.v = flr(rnd(2))
if x.x < 1 or x.x > 14 then
x.v = 3
end
if x.v == 0 then
x.v = "."
elseif x.v ==1 then
x.v = ","
else
x.v = "0"
end
add(y,x)
end
end
I've tried accessing the value using
print(t[1][3])
But this only prints back a nil value, how would I code this to show whats stored within the value within these two tables?

You have the nesting as follows:
y = {x_1, x_2, x_3, ...}
where, each of x_i is of the form:
x = {
x = p,
y = q,
v = r
}
so, you will have the indexing for each x element as y[i], and each y[i] contains 3 attributes:
print(y[1].x)
will give you x_1.x

You want to create a 2-dimensional table, but only create a 1-dimensional one.
Fix your code to look somewhat like this
y = {}
for _y=1,16 do
y[_y] = {}
for _x=1,16 do
y[_y][_x]= "your data"
end
end

Related

Split string to numbers in Lua

I've a problem with splitting this:
x = "-301 1021"
to this
x = -301
y = 1021
In C++ this is easier but I really don't know how to do it in Lua. I tried do it like
string1 .. string[i]
#Edit
I've made it like this but now it doesn't get values which are negative
for coordinate in ActualCoords:gmatch("%w+") do
table.insert(coordinates, coordinate)
end
x = coordinates[1];
x = tonumber(x);
z = coordinates[2];
z = tonumber(z);
Assuming your input is regular:
restults = {};
for m in str:gmatch("[^%s]+") do
results[#results+1] = m+0;
end
If input is irregular, meaning you need to verify that its not random things separated by spaces, you need to make a more complex pattern, eg.
"[%deE.-]+"
Try this:
s = "-301 1021"
x,y = s:match("(%S+)%s+(%S+)")
x,y = tonumber(x), tonumber(y)
You can use LPEG for such parsing tasks.
local lpeg = assert(require"lpeg")
local R, S = lpeg.R, lpeg.S
local integer = (S'+-'^-1 * R("09")^1) / tonumber
local space = S(" \t")^0
local x, y = lpeg.match((integer * space)^1, "-301 1021")
print(x,y)
or try this
local s = "-301 1021 -300 1022 -20 -1000"
local coord = {}
for x,y in s:gmatch("(-?%d+).-(-?%d+)") do
coord[#coord+1] = { x=tonumber(x), y=tonumber(y) }
end
print( coord[1].x, coord[1].y)
print( coord[2].x, coord[2].y)
print( coord[3].x, coord[3].y)

Why is my lua table object empty?

I create a lua table object called Map in my Map module, and this function creates a new instance:
function Map:new (o)
o = o or {
centers = {},
corners = {},
edges = {}
}
setmetatable(o, self)
self.__index = self
return o
end
and in my island module I put in this code in the first few lines:
local map = require (*map module location*)
Island = map:new ()
and when I print the number of centers, corners, and tables, they all come out to 0.
I have separate modules for Corner:new (), Center:new (), and Edge:new ()
Why does the length of centers, corners, and edges output as 0?
Edit:
This is what I input into the centers table for example(corners and edges is similar)
function pointToKey(point)
return point.x.."_"..point.y
end
function Map:generateCenters(centers)
local N = math.sqrt(self.SIZE)
for xx = 1, N do
for yy = 1, N do
local cntr = Center:new()
cntr.point = {x = 0.5+xx - 1, y = 0.5+yy - 1}
centers[pointToKey(cntr.point)] = cntr
end
end
return centers
end
The size is always a perfect square
This seems to be a problem with variable scope. Firstly, in instantiating a new Map, the o that is returned should be local:
function Map:new (o)
local o = o or { -- this should be local
centers = {},
corners = {},
edges = {}
}
setmetatable(o, self)
self.__index = self
return o
end
When you pass a pointer to a table to Map:generateCenters(), there is no need to return that pointer. The centers have been added to that table:
function Map:generateCenters(centers)
local N = math.sqrt(self.SIZE)
for xx = 1, N do
for yy = 1, N do
local cntr = Center:new()
cntr.point = {x = 0.5+xx - 1, y = 0.5+yy - 1}
centers[pointToKey(cntr.point)] = cntr -- HERE you're adding to the table passed as an argument
end
end
-- return centers --> NO NEED TO RETURN THIS
end
Lastly, you would do:
local map = require( "map" )
local island = map:new()
map:generateCenters( island.centers )
You are saying, "Put the centers into the table pointed to by the table value corresponding to the key called centers in the table called island".
Lastly, note that
local t = island.centers
print( #t )
will still not output the number of elements in the table centers because there are gaps keys (i.e. they don't go {0,1,2,3,4,..} but rather whatever string the pointToKey() function returns ). To count the elements in centers, you could do:
local count = 0
for k,v in pairs( island.centers ) do
count = count + 1
end
print( count )

Lua #Table returning 0, despite Table containing 3 elements (tables)? [duplicate]

Sounds like a "let me google it for you" question, but somehow I can't find an answer. The Lua # operator only counts entries with integer keys, and so does table.getn:
tbl = {}
tbl["test"] = 47
tbl[1] = 48
print(#tbl, table.getn(tbl)) -- prints "1 1"
count = 0
for _ in pairs(tbl) do count = count + 1 end
print(count) -- prints "2"
How do I get the number of all entries without counting them?
You already have the solution in the question -- the only way is to iterate the whole table with pairs(..).
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
Also, notice that the "#" operator's definition is a bit more complicated than that. Let me illustrate that by taking this table:
t = {1,2,3}
t[5] = 1
t[9] = 1
According to the manual, any of 3, 5 and 9 are valid results for #t. The only sane way to use it is with arrays of one contiguous part without nil values.
You can set up a meta-table to track the number of entries, this may be faster than iteration if this information is a needed frequently.
The easiest way that I know of to get the number of entries in a table is with '#'. #tableName gets the number of entries as long as they are numbered:
tbl={
[1]
[2]
[3]
[4]
[5]
}
print(#tbl)--prints the highest number in the table: 5
Sadly, if they are not numbered, it won't work.
There's one way, but it might be disappointing: use an additional variable (or one of the table's field) for storing the count, and increase it every time you make an insertion.
count = 0
tbl = {}
tbl["test"] = 47
count = count + 1
tbl[1] = 48
count = count + 1
print(count) -- prints "2"
There's no other way, the # operator will only work on array-like tables with consecutive keys.
function GetTableLng(tbl)
local getN = 0
for n in pairs(tbl) do
getN = getN + 1
end
return getN
end
You're right. There are no other way to get length of table
You could use penlight library. This has a function size which gives the actual size of the table.
It has implemented many of the function that we may need while programming and missing in Lua.
Here is the sample for using it.
> tablex = require "pl.tablex"
> a = {}
> a[2] = 2
> a[3] = 3
> a['blah'] = 24
> #a
0
> tablex.size(a)
3
local function CountedTable(x)
assert(type(x) == 'table', 'bad parameter #1: must be table')
local new_t = {}
local mt = {}
-- `all` will represent the number of both
local all = 0
for k, v in pairs(x) do
all = all + 1
end
mt.__newindex = function(t, k, v)
if v == nil then
if rawget(x, k) ~= nil then
all = all - 1
end
else
if rawget(x, k) == nil then
all = all + 1
end
end
rawset(x, k, v)
end
mt.__index = function(t, k)
if k == 'totalCount' then return all
else return rawget(x, k) end
end
return setmetatable(new_t, mt)
end
local bar = CountedTable { x = 23, y = 43, z = 334, [true] = true }
assert(bar.totalCount == 4)
assert(bar.x == 23)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = 24
bar.x = 25
assert(bar.x == 25)
assert(bar.totalCount == 4)
I stumbled upon this thread and want to post another option. I'm using Luad generated from a block controller, but it essentially works by checking values in the table, then incrementing which value is being checked by 1. Eventually, the table will run out, and the value at that index will be Nil.
So subtract 1 from the index that returned a nil, and that's the size of the table.
I have a global Variable for TableSize that is set to the result of this count.
function Check_Table_Size()
local Count = 1
local CurrentVal = (CueNames[tonumber(Count)])
local repeating = true
print(Count)
while repeating == true do
if CurrentVal ~= nil then
Count = Count + 1
CurrentVal = CueNames[tonumber(Count)]
else
repeating = false
TableSize = Count - 1
end
end
print(TableSize)
end
seems when the elements of the table is added by insert method, getn will return correctly. Otherwise, we have to count all elements
mytable = {}
element1 = {version = 1.1}
element2 = {version = 1.2}
table.insert(mytable, element1)
table.insert(mytable, element2)
print(table.getn(mytable))
It will print 2 correctly

Lua table.concat

Is there a way to use the arg 2 value of table.concat to represent the current table index?
eg:
t = {}
t[1] = "a"
t[2] = "b"
t[3] = "c"
X = table.concat(t,"\n")
desired output of table concat (X):
"1 a\n2 b\n3 c\n"
Simple answer : no.
table.concat is something really basic, and really fast.
So you should do it in a loop anyhow.
If you want to avoid excessive string concatenation you can do:
function concatIndexed(tab,template)
template = template or '%d %s\n'
local tt = {}
for k,v in ipairs(tab) do
tt[#tt+1]=template:format(k,v)
end
return table.concat(tt)
end
X = concatIndexed(t) -- and optionally specify a certain per item format
Y = concatIndexed(t,'custom format %3d %s\n')
I don't think so: how would you tell it that the separator between keys and values is supposed to be a space, for example?
You can write a general mapping function to do what you'd like:
function map2(t, func)
local out = {}
for k, v in pairs(t) do
out[k] = func(k, v)
end
return out
end
function joinbyspace(k, v)
return k .. ' ' .. v
end
X = table.concat(map2(t, joinbyspace), "\n")
No. But there is a work around:
local n = 0
local function next_line_no()
n = n + 1
return n..' '
end
X = table.concat(t,'\0'):gsub('%f[%Z]',next_line_no):gsub('%z','\n')
function Util_Concat(tab, seperator)
if seperator == nil then return table.concat(tab) end
local buffer = {}
for i, v in ipairs(tab) do
buffer[#buffer + 1] = v
if i < #tab then
buffer[#buffer + 1] = seperator
end
end
return table.concat(buffer)
end
usage tab is where the table input is and seperator be both nil or string (if it nil it act like ordinary table.concat)
print(Util_Concat({"Hello", "World"}, "_"))
--Prints
--Hello_world

How to get number of entries in a Lua table?

Sounds like a "let me google it for you" question, but somehow I can't find an answer. The Lua # operator only counts entries with integer keys, and so does table.getn:
tbl = {}
tbl["test"] = 47
tbl[1] = 48
print(#tbl, table.getn(tbl)) -- prints "1 1"
count = 0
for _ in pairs(tbl) do count = count + 1 end
print(count) -- prints "2"
How do I get the number of all entries without counting them?
You already have the solution in the question -- the only way is to iterate the whole table with pairs(..).
function tablelength(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
Also, notice that the "#" operator's definition is a bit more complicated than that. Let me illustrate that by taking this table:
t = {1,2,3}
t[5] = 1
t[9] = 1
According to the manual, any of 3, 5 and 9 are valid results for #t. The only sane way to use it is with arrays of one contiguous part without nil values.
You can set up a meta-table to track the number of entries, this may be faster than iteration if this information is a needed frequently.
The easiest way that I know of to get the number of entries in a table is with '#'. #tableName gets the number of entries as long as they are numbered:
tbl={
[1]
[2]
[3]
[4]
[5]
}
print(#tbl)--prints the highest number in the table: 5
Sadly, if they are not numbered, it won't work.
There's one way, but it might be disappointing: use an additional variable (or one of the table's field) for storing the count, and increase it every time you make an insertion.
count = 0
tbl = {}
tbl["test"] = 47
count = count + 1
tbl[1] = 48
count = count + 1
print(count) -- prints "2"
There's no other way, the # operator will only work on array-like tables with consecutive keys.
function GetTableLng(tbl)
local getN = 0
for n in pairs(tbl) do
getN = getN + 1
end
return getN
end
You're right. There are no other way to get length of table
You could use penlight library. This has a function size which gives the actual size of the table.
It has implemented many of the function that we may need while programming and missing in Lua.
Here is the sample for using it.
> tablex = require "pl.tablex"
> a = {}
> a[2] = 2
> a[3] = 3
> a['blah'] = 24
> #a
0
> tablex.size(a)
3
local function CountedTable(x)
assert(type(x) == 'table', 'bad parameter #1: must be table')
local new_t = {}
local mt = {}
-- `all` will represent the number of both
local all = 0
for k, v in pairs(x) do
all = all + 1
end
mt.__newindex = function(t, k, v)
if v == nil then
if rawget(x, k) ~= nil then
all = all - 1
end
else
if rawget(x, k) == nil then
all = all + 1
end
end
rawset(x, k, v)
end
mt.__index = function(t, k)
if k == 'totalCount' then return all
else return rawget(x, k) end
end
return setmetatable(new_t, mt)
end
local bar = CountedTable { x = 23, y = 43, z = 334, [true] = true }
assert(bar.totalCount == 4)
assert(bar.x == 23)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = nil
assert(bar.totalCount == 3)
bar.x = 24
bar.x = 25
assert(bar.x == 25)
assert(bar.totalCount == 4)
I stumbled upon this thread and want to post another option. I'm using Luad generated from a block controller, but it essentially works by checking values in the table, then incrementing which value is being checked by 1. Eventually, the table will run out, and the value at that index will be Nil.
So subtract 1 from the index that returned a nil, and that's the size of the table.
I have a global Variable for TableSize that is set to the result of this count.
function Check_Table_Size()
local Count = 1
local CurrentVal = (CueNames[tonumber(Count)])
local repeating = true
print(Count)
while repeating == true do
if CurrentVal ~= nil then
Count = Count + 1
CurrentVal = CueNames[tonumber(Count)]
else
repeating = false
TableSize = Count - 1
end
end
print(TableSize)
end
seems when the elements of the table is added by insert method, getn will return correctly. Otherwise, we have to count all elements
mytable = {}
element1 = {version = 1.1}
element2 = {version = 1.2}
table.insert(mytable, element1)
table.insert(mytable, element2)
print(table.getn(mytable))
It will print 2 correctly

Resources