Hello I have a little problem with lua. I want to access one of the tables containing the route information depending on the route variable defined on the start of the script. But everytime I run the program I always get nil as an answer. Does anybody know how to fix that?
route = 1
local eastCityRoute = {
{name = "ecr-stop1"},
{name = "ecr-stop2"},
{name = "ecr-stop3"},
}
local westCityRoute = {
{name = "wcr-stop1"},
{name = "wcr-stop2"},
{name = "wcr-stop3"},
}
routes = {}
routes[1] = eastCityRoute
routes[2] = westCityRoute
print(routes[route][name])
local eastCityRoute = {
{name = "ecr-stop1"},
{name = "ecr-stop2"},
{name = "ecr-stop3"},
}
is short for
local eastCityRoute = {
[1] = {["name"] = "ecr-stop1"},
[2] = {["name"] = "ecr-stop2"},
[3] = {["name"] = "ecr-stop3"},
{
Let's look at your remaining code:
You create a global table routes and store two tables eastCityRoute and westCityRoute in it.
routes = {}
routes[1] = eastCityRoute
routes[2] = westCityRoute
Now you try this:
print(routes[route][name])
route is 1 so routes[route] is equivalent to routes[1] which resolves to eastCityRoute.
But eastCityRoute[name] is equal to eastCityRoute[nil]. As eastCityRoutes does not have a metatable with a proper __index metavalue eastCityRoute[nil] resolves to nil.
eastCityRoute[name] is not the same as eastCityRoute["name"]!!!
In one case you index with a variable and in the other case you index with a literal string.
Please read the Lua Reference Manual.
Related
have a data like this
result = {
[1] = { ["identifier"] = MMK18495,["vehicles"] = {"vehN":"Caracara 4x4","vehM":"caracara2","totals":3},["id"] = 1,} ,
[2] = { ["identifier"] = MMK18495,["vehicles"] = {"vehN":"Sandking SWB","vehM":"sandking2","totals":3},["id"] = 2,} ,
[3] = { ["identifier"] = MMK18495,["vehicles"] = {"totals":5,"vehN":"Caracara 4x4","vehM":"caracara2"},["id"] = 3,} ,
}
trying to sort this data to a menu like this
for i=1, #result, 1 do
local ownedcars = result[i].vehicles
print(dump(ownedcars))
for _,v in pairs(ownedcars) do -- <- the error is here
menu[#menu+1] = {
header = " Model "..v.vehM.." Name "..v.vehN.." quantity"..v.totals,
txt = "",
}
end
end
the output of ownedcars
{"vehN":"Caracara 4x4","vehM":"caracara2","totals":3}
but here is the error
As others have commented, this is not a Lua table. When inputting JSON tables, Lua reads them as strings. You will first need to convert your given JSON string into Lua. Thankfully, others have already done this. I will refer you to this question which has answers that solved this problem.
Once you've converted your JSON string to a Lua table, you should be good to go.
I'm trying to figure out how to dynamically build a series of sub-tables inside a lua table. For example
function BuildsubTable()
local oTable = {}
local name = {"P1","P2"}
for i = 1, 2 do
oTable[i] = {name = name[i], "x" = i + 2, "y" = i + 1}
end
return oTable
end
expected output:
oTable = {
{name = "P1", "x"=3, "y"=2},
{name = "P2", "x"=4, "y"=3}
}
Which obviously doesn't work, but you get the idea of what I'm trying to do. This is a rather simple task but in LUA 5.3 this is proving to be difficult. I cannot find a good example of building a table in this manner. Any solutions or other ideas would be appreciated. In Python I would use a class or a simple dictionary.
Your problem is that you quote the string indices. The generic syntax for declaring a table key inside the table constructor is [<key>] = <value>, for example, [20] = 20 or ["x"] = i + 2.
A shorthand for ["<key>"] = <value>, that is, for string indices that are valid variable names, you can write <key> = <value>, for example x = i + 2.
In your code you use a mix of both and write { ..., "x" = i + 2, ... }. A quick google search shows me that in Python, which you mention, you quote string keys in dictionaries, so you probably mixed that up with Lua?
EDIT: I noticed this a bit late, but you can also use ipairs to iterate the first table and table.insert to insert values:
function BuildsubTable()
local oTable = {}
local name = {"P1","P2"}
for i,name in ipairs(name) do
table.insert(oTable, {name = name, "x" = i + 2, "y" = i + 1})
end
return oTable
end
Use
oTable[i] = {name = name[i], x = i + 2, y = i + 1}
DarkWiiPlayers & lhf's answers are the proper way.
But here is how you can fix your current code if you intend to use a string as a key
function BuildsubTable()
local oTable = {}
local name = {"P1","P2"}
for i = 1, 2 do
oTable[i] = {name = name[i], ["x"] = i + 2, ["y"] = i + 1}
end
return oTable
end
Output
{
[1] = { ['name'] = 'P1', ['x'] = 3, ['y'] = 2},
[2] = { ['name'] = 'P2', ['x'] = 4, ['y'] = 3}
}
I have a table called "inventory", initialized like so:
inventory = {}
inventory[1] = { qty = 0 }
I want to add more data to this table, at the index 1, eg:
val = { id = "example" }
inventory[1] = inventory[1], val
Is there a way I can do this while preserving the data that is already in this table at this index?
The final result should be something like:
inventory[1] = { qty = 0, id = "example" }
But if I try to print the id after trying this code I get:
print(inventory[1].id) == Nil
inventory[1].id = "example"
or
inventory[1]["id"] = "example"
or
this other SO answer with first_table being inventory[1] and second_table being val.
FWIW, you'd need 2 variables on the left side of the expression for inventory[1] = inventory[1], val to work: a, b = x, y.
You need to take the first key in the table and use it:
local inventory = {}
inventory[1] = { qty = 0 }
local val = { id = "example" }
--
local KeyName = next(val)
inventory[1][KeyName] = val[KeyName]
print(inventory[1][KeyName])
-- or
print(inventory[1].id)
I'm working on a game where a bunch of characters will be generated on the fly, based on some constraints defined either in the project or externally via mod files. I am using MoonSharp Lua (5.2) interpreter for interfacing with my C# code, and Lua tables to store the constraint presets. As an example:
require "Defaults"
AgePresets = {}
-- Single value
AgePresets.Newborn = 0
-- Simple ranges
AgePresets.Default = defaultAgeRange --referring to the Defaults require
AgePresets.Child = {1, 12}
AgePresets.Teenager = {13, 19}
AgePresets.YoungAdult = {20, 29}
AgePresets.Adult = {30, 40}
AgePresets.MiddleAge = {40, 60}
AgePresets.Senior = {61, 80}
AgePresets.Elder = {81, 99}
AgePresets.Methuselah = {100, 150}
AgePresets.Methuselah2 = {150, 200}
-- Weighted ranges // again referring to previously defined elements to keep things concise
AgePresets.Tween = {
{weight = 1, minmax = AgePresets.Teenager },
{weight = 1, minmax = AgePresets.YoungAdult }
}
This works fine, but from an end-user point of view, there's a lot of unnecessary typing involved. We are clearly working on AgePresets here but it is still mentioned as a prefix before every member name.
I could of course define AgePresets as an array, like AgePresets = { Child = {}, Teenager = {} } but the problem with that is then I cannot refer to previously defined elements in the array.
This doesn't work:
AgePresets = {
Child = {1,12},
RefToChild = Child, //attempt to index a nil value exception
Teen = {13,19}
}
What I ideally want to achieve is a clean, concise way for users to enter this data in, like in the first example but without having to put AgePresets. prefix before everything. How do I go about declaring a scope in a file such that all succeeding members defined in the file will be within that scope, while maintaining the ability to refer to other members defined previously in the scope?
AgePresets = setmetatable({}, {__index = _G})
do
local _ENV = AgePresets
Newborn = 0
Child = {1,12}
RefToChild = Child -- this ref is Ok
Teen = {13,19}
YoungAdult = {20,29}
Tween = {
{weight = 1, minmax = Teen },
{weight = 1, minmax = YoungAdult }
}
rnd = math.random(10) -- global functions are available here
end
setmetatable(AgePresets, nil)
You can mix the two styles: table constructor for fields that don't need to reference variables that aren't in scope yet, followed by assignment statements for the rest.
I would do that unless the order of the fields in the code significantly enhanced comprehension.
All the examples for splitting strings generate arrays. I want the following
Given string like x.y.z e.g. storage.clusters.us-la-1
How do I generate a table from that resembling
x = {
y = {
z = {
}
}
}
Below is a function that should do what you want.
function gen_table(str, existing)
local root = existing or {}
local tbl = root
for p in string.gmatch(str, "[^.]+") do
local new = tbl[p] or {}
tbl[p] = new
tbl = new
end
return root
end
Usage:
local t = gen_table("x.y.z")
local u = gen_table("x.y.w", t)
t.x.y.z.field = "test1"
t.x.y.w.field = "test2"