This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
ChaddJackson12's profile picture

[Lua][Help]Tables Help

Started by ChaddJackson12, 04 December 2012 - 01:08 PM
ChaddJackson12 #1
Posted 04 December 2012 - 02:08 PM
Is there a way to create tables inside of tables using a lua command? Like this: (The tables wouldn't exist to begin with)

table.insert(table.table2.table3, "Stuff")

or like this:

table.insert(table.table2, "Stuff") – Where i would be changing?

Please help me if you can, thanks.
Dlcruz129 #2
Posted 04 December 2012 - 03:04 PM
I don't have much experience with tables, but my guess would be the textutils.serialize() and textutils.unserialize() functions. Serialize turns the table into a string, and unserialize switches it back into a table. This is also useful for sending tables over rednet, as rednet.send() only works with strings.

Hope I helped!
Lyqyd #3
Posted 04 December 2012 - 03:11 PM
That is entirely unrelated to the question as asked.

Tables within tables are easy:


aTable = {} --declare a table.
aTable[1] = {} --declare a table at index 1 of aTable.
aTable[1][1] = "bob" -set the value of the first index of the table stored in the first index of aTable.
ChaddJackson12 #4
Posted 04 December 2012 - 05:29 PM
That is entirely unrelated to the question as asked.

Tables within tables are easy:


aTable = {} --declare a table.
aTable[1] = {} --declare a table at index 1 of aTable.
aTable[1][1] = "bob" -set the value of the first index of the table stored in the first index of aTable.
Well, I couldn't find a good way to word it. I do know about making tables within tables. But I would like to make tables inside tables with a Lua command. This is because what would be inside a table would not be a 'set' value. What I am looking for is a way to make a currently non existing table, exist. But the table would have a table inside it with data that I wouldn't know. Here is an example:

ProgramList = {
  [1] = { ProgramDirectory = "Program1", ProgramName = "Program1.lua" },
  [2] = { ProgramDirectory = "Program2", ProgramName = "Program2.lua" }
}
I am wondering how to be able to create that type of table without actually knowing what would go in it. I have tried a lot of different code and can't seem to get it to work. Please help if you can. Also, I'd prefer to use that layou if possible. Thanks in advance.
Lyqyd #5
Posted 04 December 2012 - 07:07 PM
Show us what you've currently got that doesn't work; we'll help you make it work. I get what you're saying, I think, but your examples are all of static data.
KaoS #6
Posted 04 December 2012 - 07:32 PM
Could you give us an example of what this would let you do, what kind of program are you making, because so far it seems like a very standard code
ChunLing #7
Posted 04 December 2012 - 09:15 PM
If you want to use this with user input (classic case of not knowing what you'll have), then it would be something like
local usercreatedtable = {}

repeat
    write("Enter a new subtable name: ")
    local stname = read()
    usercreatedtable[stname] = {}
    write("Enter new subtable size: ")
    local stsize = tonumber(read())
    for i = 1,stsize do
        write("Enter subtable entry "..i..": ")
        usercreatedtable[stname][i] = read()
    end
    write("Do you wish to enter additional subtables?")
until read() == "no"
Just so that you can see what Lyqyd proposed in context of being used with unknown input, not that this is likely useful code. Now, here we should end up with a table of subtables that have user entered names, user entered sizes, and user entered data in them.
ChaddJackson12 #8
Posted 05 December 2012 - 04:13 AM
Ok here is what I want to do. I want to create a menu from a table. I already know how I would do that, here is the code for that.


function PrintMenu(menu)
for i = 1, #menu do
  if i == SelectedItem then
   term.setTextColor(colors.yellow)
   print(menu[i].option) -- Option in this case would be the name of the folder the program is in.
   term.setTextColor(colors.white)
  else
   term.setTextColor(colors.gray)
   print(menu[i].option)
   term.setTextColor(colors.white)
  end
end
end

function KeyHandler(key, menu)
if key == 28 then
  UseOption(menu)
elseif key == 200 then
  if SelectedItem > 1 then
   SelectedItem = SelectedItem - 1
  else
   SelectedItem = #menu
  end
elseif key == 208 then
  if SelectedItem < #menu then
   SelectedItem = SelectedItem + 1
  else
   SelectedItem = 1
  end
end
end

function UseOption(menu)
shell.run(menu[SelectedItem].Option .. "/" .. menu[SelectedItem].ProgramName)
end

That is the code to print and handle the menu. The menu that I want to create is one that contains a fs.list(). This is how the default menus look that those functions handle:


MainMenu = {
[1] = { Option = "Hello", ProgramName = "Hello.lua" },
[2] = { Option = "Goodbye", ProgramName = "Goodbye.lua }
}

The "Option" In that menu would be the directory that the program is in (It would be in a directory for a reason…) and the "ProgramName" is the name of the program inside the folder that should be ran when that option is selected. The only difference between the name of the directory and the program name is a ".lua" after the "ProgramName".

What I wanted to do is have a menu creating function. Which would set up the table for the menu, as it would not already exist, and I can't create it because I don't know how many programs it would create so I can't create the second table, with [#]'s. This is how I wanted to do that.


function CreateMenu()
ProgramList = fs.list("Programs")
i = 1
for k, v in pairs(ProgramList) do
  if fs.isDir(v) then
   table.insert(ProgramMenu[i].Option, v)
   table.insert(ProgramMenu[i].ProgramName, v .. ".lua")
   i = i + 1
  end
end
end

The way that it I thought it would work:


-- Pretend all the code from above is in here...
local UseProgramMenu = false
local SelectedItem = 1
local InMain = true

function Main()
CreateMenu()
SelectedItem = 1 -- Put in here again just in case...
UseProgramMenu = true
while UseProgramMenu do
  term.clear()
  term.setCursorPos(1, 1)
  print("Program Menu\n")
  PrintMenu(ProgramMenu)

  event, key = os.pullEvent("key")
  KeyHandler(key, ProgramMenu)
end
end

while InMain do
Main()
end

You may not need all the code from above, but that is all that it should need to be. I have tried this code and I get an error in the "PrintMenu()" function on the line of the "for" loop. Where it says "for i = 1, #menu do" – Attempt to index a nil value, or something like that. Anyways. Please help me out if you can, that is how I thought it would work.
ChaddJackson12 #9
Posted 05 December 2012 - 04:15 AM
I don't have much experience with tables, but my guess would be the textutils.serialize() and textutils.unserialize() functions. Serialize turns the table into a string, and unserialize switches it back into a table. This is also useful for sending tables over rednet, as rednet.send() only works with strings.

Hope I helped!
That isn't what I asked for, but this will help me with other things. Thanks for the feedback!
Bubba #10
Posted 05 December 2012 - 04:20 AM
Okay, well I do not see you ever declare the variable ProgramMenu in your code, which would be why it is giving you that particular error. I don't know if that is because you just did forget to paste it, but just in case could you please provide the entire code rather than just separated pieces? It's difficult to tell what you are trying to do when the code is separated like that.

What you are trying to do, however, is entirely possible. You can have as many tables within tables as you want (within reason that is).
ChaddJackson12 #11
Posted 05 December 2012 - 04:31 AM
Okay, well I do not see you ever declare the variable ProgramMenu in your code, which would be why it is giving you that particular error. I don't know if that is because you just did forgot to paste it, but just in case could you please provide the entire code rather than just separated pieces? It's difficult to tell what you are trying to do when the code is separated like that.

What you are trying to do, however, is entirely possible. You can have as many tables within tables as you want (within reason that is).
The above code is the entire code. The variable "ProgramMenu" is actually a CREATED table, and if you look in where I pasted the "CreateMenu()" function, it shows where it gets the info from the fs.list(). I figured table.insert would also create a table. But, that is why I am here, is to figure out how I can create a non existing table, because as I have mentioned before is I could only create the first table. I can't create the second table (The table inside the first) Because I wouldn't have a 'set' number of those. Look below:

ProgramMenu = {
[1] = { Option = "Hello", ProgramName = "Hello.lua" },
[2] = { Option = "Goodbye", ProgramName = "Goodbye.lua" }
}
Where the [1], and [2] are, those are the tables inside the tables. If you can see what I mean, each program would have its own "[#]", and I don't know how many programs there would be, because that could change, so I can't create those tables, I have to have the function "CreateMenu()" do it. The only thing I would be able to create is "ProgramMenu = {}", the other stuff would have to be CREATED by the function. I need help with the function to create it.

(I also would like to keep that layout, rather than the table created by fs.list() )

Sorry if that doesn't make sense, I still cannot figure out a good way to word it… XD
Doyle3694 #12
Posted 05 December 2012 - 04:36 AM
lets say like this:

words = {} -- I make an empty table.
while true do -- Start a while true loop
   input = read() -- Read something
   table.insert(words, input) -- I insert input into the table words
   for i, q in pairs(words) do -- start a loop of all the values in words
	  print(q) -- print the value currently selected
   end -- end the loop
   input = "" -- set input equal to nothing
end -- and end the while true loop

ChaddJackson12 #13
Posted 05 December 2012 - 04:40 AM
lets say like this:

words = {} -- I make an empty table.
while true do -- Start a while true loop
   input = read() -- Read something
   table.insert(words, input) -- I insert input into the table words
   for i in pairs words do -- start a loop of all the values in words
	  print(i) -- print the value currently selected
   end -- end the loop
   input = "" -- set input equal to nothing
end -- and end the while true loop

Right, but you're only inserting data into the first table, when I want to insert data into a table INSIDE the first table. Like this:

ProgramMenu = {
[1] = {} -- CREATE, and then INSERT the data into table [1]. This table would be the information for the first discovered program.
}

Also, I can't create the [1], [2], [3], ects… Because I don't know how many programs there would be…
Doyle3694 #14
Posted 05 December 2012 - 04:48 AM
well they automatically get a value without being assigned one, so

test = {{},{},{}}
would actually work for example. these 3 tables would be refered as test[1], test[2] and test[3]
Lyqyd #15
Posted 05 December 2012 - 04:50 AM
Of course you can create them; you do it inside the loop. ProgramMenu = {}. Then you fill values. You do need to declare ProgramMenu at some point, though. Just make sure to declare the table if there isn't already one before you try to fill it with values.
ChaddJackson12 #16
Posted 05 December 2012 - 04:55 AM
Of course you can create them; you do it inside the loop. ProgramMenu = {}. Then you fill values. You do need to declare ProgramMenu at some point, though. Just make sure to declare the table if there isn't already one before you try to fill it with values.
I'd like to know how to create a non declared table. The reason I can't declare the tables is because I don't know how many there would be inside the first table, such as the number of programs. Isn't there a table.create()? For creating tables to insert data into?
Lyqyd #17
Posted 05 December 2012 - 05:08 AM

local ProgramMenu = {} --declare this table
function CreateMenu()
ProgramList = fs.list("Programs")
i = 1
for k, v in pairs(ProgramList) do
  if fs.isDir(v) then
   ProgramMenu[i] = {} --declare the table when you need it
   ProgramMenu[i].Option = v --insert these as values rather than trying to use table.insert
   ProgramMenu[i].ProgramName = v .. ".lua"
   i = i + 1
  end
end
end

Was that really that hard?
ChaddJackson12 #18
Posted 05 December 2012 - 05:10 AM

local ProgramMenu = {} --declare this table
function CreateMenu()
ProgramList = fs.list("Programs")
i = 1
for k, v in pairs(ProgramList) do
  if fs.isDir(v) then
   ProgramMenu[i] = {} --declare the table when you need it
   ProgramMenu[i].Option = v --insert these as values rather than trying to use table.insert
   ProgramMenu[i].ProgramName = v .. ".lua"
   i = i + 1
  end
end
end

Was that really that hard?
Perhaps it was hard to get what I needed across… It seems all I needed was the ProgramMenu = {}, thanks for you help!
Doyle3694 #19
Posted 05 December 2012 - 05:11 AM
Well yeah, be more specific next time ;)/>
ChunLing #20
Posted 05 December 2012 - 10:36 AM
Or just read the replies, Lyqyd gave you that in the second reply.
ChaddJackson12 #21
Posted 05 December 2012 - 12:36 PM
Or just read the replies, Lyqyd gave you that in the second reply.
Yeah, in a sense he did. But I took it as him declaring the tables himself, instead of with a function.
ChunLing #22
Posted 05 December 2012 - 07:00 PM
Yeah…sometimes the right answer can look too easy to seem right. That's why I made it look a little harder ;)/>