Lua how to access specific data in a nested table - lua

I parsed some data from a CSV file to a Lua table.
Lets say the table looks like this just bigger
tab {
{ id = 1761, anotherID=2, ping=pong}
{ id = 2071, anotherID=4, ping=notpong}
}
Now I want to know every ID (without displaying any other data yet) to store them in another table for some time.
I am completely lost here for now..
Using what you wrote I rewrote it a bit and went to have:
minitab = {}
for i, value in ipairs(tab) do
local id = value.id
local anotherID = value.anotherID
minitab[id] = anotherID
end
Would that work? In fact i later want to get just 2 values of a way larger array (around 30 datas) - but I can only push a single array to a GUI dropdown. I want to save the ID as a key and the "anotherID" value wich will be a text after that key so if a ask for the 2071st value it displays the "name" 4

The code below stores the ids as keys in another table:
id={}
for k,v in ipairs(tab) do
id[v.id]=true
end
You can then traverse id with pairs to list the ids.
If you want to remember where each id came from, use id[v.id]=k in the loop.

Based on your question, you can use this code to traverse your data table tab and get minitab to be used for your GUI array:
--data
tab = {
{id = "4204", label = "2", desc = "Roancyme"},
{id = "5517", label = "9", desc = "Bicktuft"},
{id = "1035", label = "3", desc = "Pipyalum"},
}
--temporary table
local minitab = {}
for i, option in ipairs(tab) do
minitab[option.id] = option.label
end
--print minitab
print('<select>')
for id, label in pairs(minitab) do
print(string.format('<option value="%s">%s</option>', id, label)) --> <option value="1035">3</option>
end
print('</select>')
print()
However, I don't think it is necessary to create a temporary table to store those values, because you can easily traverse your original table tab and directly pull out the output you need; like this:
--print directly from tab
print('<select>')
for i, option in ipairs(tab) do
print(string.format('<option value="%s">%s</option>', option.id, option.label)) --> <option value="1035">3</option>
end
print('</select>')
print()
Unless you need to work with it before displaying the list on the drop down (e.g. add some prefix to the label, sort minitab by the label, etc); but you don't want to disturb the original data table tab. In this case, it would make sense to use the temporary table.
--format values in temporary table
local minitab = {}
for i, option in ipairs(tab) do
local minitabID = option.id
local minitabLabel = string.format('Item %s - %s', option.label, option.desc)
table.insert(minitab, {id = minitabID, label = minitabLabel})
end
--sort temporary table
table.sort(minitab, function (o1, o2) return o2.label > o1. label end)
--print formatted values from temporary table
print('<select>')
for i, option in ipairs(minitab) do
print(string.format('<option value="%s">%s</option>', option.id, option.label)) --> <option value="4204">Item 2 - Roancyme</option>
end
print('</select>')
NB: Please take a note on which table iteration uses ipairs and which one uses pairs. See the complete code snippet here.

Related

Insert elements to a table inside other table

I need help to know how to do for use table.insert, and insert elements in to one table that is in to another table. This what i have:
Table = {} --Main table
function InsertNewValues()
local TIME = --Any value, string or integer
local SIGNAL = --Any value, string or integer
table.insert(Table, {TIME, SIGNAL})
end
Ok, this allow me to insert the values of TIME and SIGNAL everytime i call that function, so the table will have:
Table[1][1] = TIME
Table[1][2] = SINGAL
...
Table[...][1] = TIME
Table[...][2] = SIGNAL
BUT ... I need to insert the values of TIME and SIGNAL in to another table that is inside of the table "Table", and that table work as a KEY to refer those values ... TIME and SIGNAL ...
therefore, the resulting table would be the following:
+Table
|
+-[1]othertable
|
+-+[1]TIME - [2]SIGNAL
+-+[1]TIME - [2]SIGNAL
+- ...
|
+-[2]othertable
|
+-+[1]TIME - [2]SIGNAL
+-+[1]TIME - [2]SIGNAL
+- ...
How can i do for do that?
----------------- EDIT -----------------
I have not explained myself well, what I need is:
Given a table called "Table", I need to be able to use "strings" as "keys" within that table. That would be:
-- Name of my "container" table
Table = {}
Values to be introduced
Time = '1 seconds' -- this value can change as desired
Value = 'logic' -- this value can change as desired
Add to my master table "Table", using the string key "RandomName"
-- "RandomName" can change as desired
function AddNewValues ()
table.insert (Table [RandomName], {Time, Value})
end
Every time I call the function "AddNewValues ()", it should add the values present in "Time" and "Value" as a "NEW ENTRY" for that "RandomName".
So the table result may should look like this:
+table -- that contains
+-RandomName-- string key to access
+--"Time,Value"
+--"Time,Value"
+--"Time,Value"
+...
And then, to be able to access the values that are inside that table, using "RandomName" as the key:
function Load()
for key, v in pairs(Table) do
a = Table[key][RandomName][1] -- reference to "Time"
b = Table[key][RandomName][2] -- reference to "Value"
print('Time: ' .. a ..'/' .. 'Value: ' .. b)
end
end
You're just not starting deep enough into the table. When you want the sequence values for the table under the key equaling the value of RandomName, just do:
function Load()
for _, v in ipairs(Table[RandomName]) do
a = v[1] -- reference to "Time"
b = v[RandomName][2] -- reference to "Value"
print('Time: ' .. a ..'/' .. 'Value: ' .. b)
end
end
Answer to original question:
It appears that you want something like this:
Table = { ["[1]othertable"] = {}, ["[2]othertable"] = {} }
table.insert(Table["[1]othertable"], {TIME, SIGNAL})
The keys are "[1]othertable" and "[2]othertable".
You might prefer to use keys like "othertable1" and "othertable2". If you use valid identifiers you can drop some of the syntax:
Table = { othertable1 = {}, othertable2 = {} }
table.insert(Table.othertable1, {TIME, SIGNAL})
In fact, you might prefer to do something similar with TIME and SIGNAL. Instead of positive integer indices, you could use string keys:
Table = { othertable1 = {}, othertable2 = {} }
table.insert(Table.othertable1, {TIME = 12.42, SIGNAL = 3.2})
print(Table.othertable1[1].TIME)

lua: user input to reference table

I am having trouble with my tables, I am making a text adventure in lua
local locxy = {}
locxy[1] = {}
locxy[1][1] = {}
locxy[1][1]["locdesc"] = "dungeon cell"
locxy[1][1]["items"] = {"nothing"}
locxy[1][1]["monsters"] = {monster1}
The [1][1] refers to x,y coordinates and using a move command I can successfully move into different rooms and receive the description of said room.
Items and monsters are nested tables since multiple items can be held there (each with their own properties).
The problem I am having is getting the items/monsters part to work. I have a separate table such as:
local monsters = {}
monsters["rat"] = {}
monsters["rat"]["Name"] = "a rat"
monsters["rat"]["Health"] = 5
monsters["rat"]["Attack"] = 1
I am using a table like this to create outlines for various enemy types. The monster1 is a variable I can insert into the location table to call upon one of these outlines, however I don't know how to reference it.
print("You are in ", locxy[x][y]["locdesc"]) -- this works
print("You can see a ", locxy[x][y]["monsters]["Name"],".") - does not work
So I would like to know how I can get that to work, I may need a different approach which is fine since I am learning. But I would also specifically like to know how to / if it possible to use a variable within a table entry that points to data in a separate table.
Thanks for any help that can be offered!
This line
locxy[x][y]["monsters]["Name"]
says
look in the locxy table for the x field
then look in the y field of that value
look in the "monsters"` field of that value
then look in the "Name" field of that value
The problem is that the table you get back from locxy[x][y]["monsters"] doesn't have a "Name" field. It has some number of entries in numerical indices.
locxy[x][y]["monsters][1]["Name"] will get you the name of the first monster in that table but you will need to loop over the monsters table to get all of them.
Style notes:
Instead of:
tab = {}
tab[1] = {}
tab[1][1] = {}
you can just use:
tab = {
[1] = {
{}
}
}
and instead of:
monsters = {}
monsters["rat"] = {}
monsters["rat"]["Name"] = "foo"
you can just use:
monsters = {
rat = {
Name = "foo"
}
}
Or ["rat"] and ["Name"] if you want to be explicit in your keys.
Similarly instead of monsters["rat"]["Name"] you can use monsters.rat.Name.

Create a numerical table from the values of a non numerical table

Backpack = {Potion = 'backpack',Stack = 'bag',Loot = 'derp', Gold = 'random'}
Backpack[1] ~= 'backpack' -- nope
As you guys can see, I cannot call Backpack[1] since its not a numeral table, how would I generate a table after the construction of Backpack, consisting only of it's values? for example:
Table_to_be_Constructed = {Value of Potion,Value of Stack,Value of Loot,Value of Gold} -- this is what i need
It seems simple but I couldn't find a way to do it.
I need it this way because i will run a numeric loop on Table_to_be_Constructed[i]
To iterate over all the key-value pairs in a table, use the pairs function:
local Table_to_be_Constructed = {}
for key, value in pairs(Backpack) do
table.insert(Table_to_be_Constructed, value)
end
Note: the iteration order is not defined. So, you might want to sort Table_to_be_Constructed afterwards.
By convention, the variable name _ is used to indicate a variable who's value won't be used. So, since you want only the values in the tables, you might write the loop this way instead:
for _, value in pairs(Backpack) do
For the updated question
Backpack has no order (The order in the constructor statement is not preserved.) If you want to add an order to its values when constructing Table_to_be_Constructed, you can do it directly like this:
local Table_to_be_Constructed = {
Backpack.Potion,
Backpack.Stack,
Backpack.Loot,
Backpack.Gold
}
Or indirectly like this:
local items = { 'Potion', 'Stack', 'Loot', 'Gold' }
local Table_to_be_Constructed = {}
for i=1, #items do
Table_to_be_Constructed[i] = Backpack[items[i]]
end

Inserting Key Pairs into Lua table

Just picking upon Lua and trying to figure out how to construct tables.
I have done a search and found information on table.insert but all the examples I have found seem to assume I only want numeric indices while what I want to do is add key pairs.
So, I wonder if this is valid?
my_table = {}
my_table.insert(key = "Table Key", val = "Table Value")
This would be done in a loop and I need to be able to access the contents later in:
for k, v in pairs(my_table) do
...
end
Thanks
There are essentially two ways to create tables and fill them with data.
First is to create and fill the table at once using a table constructor. This is done like follows:
tab = {
keyone = "first value", -- this will be available as tab.keyone or tab["keyone"]
["keytwo"] = "second value", -- this uses the full syntax
}
When you do not know what values you want there beforehand, you can first create the table using {} and then fill it using the [] operator:
tab = {}
tab["somekey"] = "some value" -- these two lines ...
tab.somekey = "some value" -- ... are equivalent
Note that you can use the second (dot) syntax sugar only if the key is a string respecting the "identifier" rules - i.e. starts with a letter or underscore and contains only letters, numbers and underscore.
P.S.: Of course you can combine the two ways: create a table with the table constructor and then fill the rest using the [] operator:
tab = { type = 'list' }
tab.key1 = 'value one'
tab['key2'] = 'value two'
Appears this should be the answer:
my_table = {}
Key = "Table Key"
-- my_table.Key = "Table Value"
my_table[Key] = "Table Value"
Did the job for me.

Nested tables and numerical keys in Lua

I'm not sure if this is possible due to the numerical indices, but hopefully someone can point me in the right direction.
Given the table of:
t = { 13, 200, 12, 15, 23 }
how can I nest a table using the numbers?
t["200"] = {"stuff", "more stuff", "even more stuff"}
doesn't seem to work, as it'll create a position 200 and fill in the empty cells with null. I'd add a letter as a suffix/prefix, but the problem comes trying to sort the table numerically. Is this even possible, or am I stuck with a different method? Thanks!
Slight edit due to a realisation:
t["200"] = {"stuff", "more stuff", "even more stuff"}
actually creates a key of "200", whereas:
t[200] = {"stuff", "more stuff", "even more stuff"}
creates the index 200 with everything else null.
First, DeadMG is correct; you used a string rather than a numerical index. However, even if you did use a number index, it wouldn't help.
If you do this:
someTable = {"value1", "value2", {"value3a", "value3b"}};
someTable[50] = {"value50a", "value50b"};
The length of the table, #someTable, will still be 3. Why? Because Lua defines arrays in a table based on contiguous elements. Remember: you can access any element of any table; they are all conceptually filled with nil until you give them an actual value.
Lua defines length for a table as the number of values in a table if you start counting from numerical index 1 until you reach the first nil value. Since someTable[4] is nil, the length is 3.
If you want to insert a new element at the end of an array table, then you can do this:
someTable[#someTable + 1] = "newValue";
The value can itself be a table:
someTable[#someTable + 1] = {"newValuea", "newValueb"};
If you're just asking how to access a nested table, that's simple, and it has nothing to do with the keys you use.
There is nothing special about nested tables. Tables are values, and table entries can be any value, including other tables.
If you have a table, and want to walk the array entries in it, you use this:
local aTable = {"first", "second", "third", ...}
for i, value in ipairs(aTable) do
--`value` contains the entries in the table.
end
A nested table is no different; it is simply a matter of getting the table.
local nestedTable = { "first", "second", "third", ...}
nestedTable[#nestedTable + 1] = {"newFirst", "newSecond", ...}
local aTable = nestedTable[#nestedTable];
for i, value in ipairs(aTable) do
--`value` contains the entries in the table.
end
Or you could just do ipairs(nestedTable[#nestedTable]). Note that the particular key used here (an integer value) is entirely unimportant. That key could have been a string, a floating-point number, another table, some user-data, etc. It doesn't matter.
Note also that we use ipairs because we only want to iterate over the array members of the table. The length of the array is defined above. If we wanted to loop over every member of the table, we would use pairs instead of ipairs. Of course, pairs does an unordered search, so it is not guaranteed to be in array order.
If you want to recursively find every element in a nested table, you can do this:
local function RecursiveSearch(aTable)
for key, value in pairs(aTable) do --unordered search
if(type(value) == "table") then
RecursiveSearch(value)
else
--Do something with this.
end
end
end
Note that the above can do an infinite loop, since it is possible for a table to have circular references:
local tableA = {}
local tableB = {tableA}
local tableA[1] = tableB
RecursiveSearch(tableA) --Infinite loop.
Perhaps it helps to view your assignment like this:
t = { [1] = 13, [2] = 200, [3] = 12, [4] = 15, [5] = 23 }
To change what is currently 200 (namely t[2]), you do:
t[2] = {"stuff", "more stuff", "even more stuff"}
Edit: that results in your table looking like this:
t = { [1] = 13, [2] = {"stuff", "more stuff", "even more stuff"}, [3] = 12, [4] = 15, [5] = 23 }
-- or, equivalent::
t = { 13, {"stuff", "more stuff", "even more stuff"}, 12, 15, 23 }
The trouble is your use of "". Your table t contains a bunch of numbers, and you're entering a string as the key. You want to iterate over the table and do... something that you didn't particularly well define. However, you can't add to a table whilst iterating over it, so you might have to do some funny stuff.
t = { 13, 200, 12, 15, 23 }
newt = {};
for key, value in pairs(t) {
newt[value] = { };
}
This will create a table entry in newt, where the key is a value in the table t, for all values in t.

Resources