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

How To Use Tables.

Started by Zudo, 29 October 2013 - 07:41 AM
Zudo #1
Posted 29 October 2013 - 08:41 AM
How to use tables

(and use them well)


Welcome to this tutorial about using tables. This tutorial is split into parts:

Part I - Creating a tableA table is a list of values, which are all stored under one variable.
In Lua, a table is an associative array, which means that any values stored in one are referenced by a key, which can be a number, string, [acronym='A boolean is a true or false value. eg 5+5=10 == true, 5+5=11 == false']boolean[/acronym] or even another table!

To make a table, simply do this:


local myTable = {}

The variable myTable is now an empty table.

Part II - Numbers as keysIf you already have a table, you can insert a value referenced by a number into the table with one of these methods:


-- This...
myTable[1] = "This is item 1 of the table"
-- ... does the same as this
myTable:insert(1, "This is item 1 of the table")

You can then refer to this value as:


print(myTable[1]) -- Prints out "This is item 1 of the table"

You can replace 1 with any number you like, and it will still work. Note that myTable:insert() will shift the positions of the other values in a table, whereas referencing the table directly (myTable[1] = "…") will overwrite the value at position 1.

Part III - Strings as keysIf you are creating an array with no specific order (e.g. a username and password table) you can also use strings as a key:


myTable["ZudoHackz"] = "MyPassword"
myTable["SomeoneElse"] = "SomePassword"

You can't use myTable:insert() with strings (I think). To reference a value, you can just do:


print(myTable["ZudoHackz"])
-- Or
print(myTable.ZudoHackz)

Part IV - Initializing a table with data already in it

local myTable = {}
myTable[1] = "blah1"
myTable[2] = "blah2"
myTable[3] = "blah3"
...

This works, but it is quicker and shorter to do this:


local myTable = {"blah1","blah2","blah3"}

If you create a table like this, myTable[1] would be set to "blah1", myTable[2] would be "blah2" etc.

You can also do this:


myTable = {[1] = "blah1", [2] = "blah2", [3] = "blah3"}

If you do it this way, you can change the order easily:


local myTable = {[3] = "blah1", [2] = "blah2", [1] = "blah3"}

Or even do this:


local myTable = {[1] = "blah1", [6] = "blah2", [300] = "blah3"}

This also works with anything else as a key:


local myTable = {["one"] = "blah1", ["two"] = "blah2", ["three"] = "blah3"}

Part V - Using tablesTables are used for storing similar information. But, they can also be used for other things, like:

Capturing return valuesSome functions, like os.pullEvent() return different amounts of return values. You could do something like this:


local a, b, c, d, e = os.pullEvent()
print(a)
print(B)/>/>/>
print(c)
print(d)
print(e)

but you still can't be sure you have saved all the return values. However, a setup like this:


local myEventData = {os.pullEvent()}
for _, value in pairs(myEventData) do
print(v)
end

would definitely capture all of the values, and definitely return them all. More on the for loop later. Anyway, if you put the function call in curly { } brackets, it will return a table. myEventData[2] in the second example is equal to b in the first example.

Please readIP.Board screwed up the third line of the first example in this section. It is print b but with brackets, rather than spaces.

This isn't really a use of the table, but it is very useful to learn about
Iterating through a tableWith the pairs() function, you can iterate through a table. Here is an example:


local myTable = {"blah1","blah2","blah3"}

for key, value in pairs(myTable) do
print("The value of the key " .. key .. " is ".. value)
end

This piece of code repeats 3 times (there are three values in the table) and prints:


The value of the key 1 is blah1
The value of the key 2 is blah2
The value of the key 3 is blah3

So this can be very useful. How about this?


local myTable = {"blah1","blah2","blah3"}

local function isInTable(table, value)
for _, v in pairs(table) do -- Use _ if you don't need that return value.
  if v == value then
   return true, k
  end
end
return false
end

isInTable(myTable, "blah1") -- Returns [true, 1]
isInTable(myTable, "blah2") -- Returns [true, 2]

isInTable(myTable, "blah3") -- Returns [true, 3]
isInTable(myTable, "blah4") -- Returns false

So iterating through tables is very, very useful.

Thank you for reading this tutorial! Please point out any mistakes, and advise me on using tables even better! :)/>/>/>

-Z
theoriginalbit #2
Posted 29 October 2013 - 10:18 AM
There is a lot that you've missed. You haven't pointed out anything such as mixing indexed and key/value elements, negative indexes, iterating through tables, both with a numerical for loop and a generic for loop (pairs/ipairs). The advantages of each type of loop (incremental/ipairs/pairs), especially when dealing with custom indexes such as a table that only contains indexes 1,2,4,17,700. There are various other improvements along these lines that you could make.

I think that maybe explaining and/or showing an example of how tables can help us capture all return results from a function call, or all arguments in a vararg function.

You also don't state why it is better (efficiency-wise and memory-wise) to define the elements in a table when invoking the table constructor. Which I think is needed rather than just stating "but it is quicker and shorter to do this"

Also consider using locals in all your code examples in an attempt to promote good coding habits.
sens #3
Posted 29 October 2013 - 10:33 AM
You also don't state why it is better (efficiency-wise and memory-wise) to define the elements in a table when invoking the table constructor. Which I think is needed rather than just stating "but it is quicker and shorter to do this"
I'm relatively new to Lua and may be mistaken about this, but what I've read seems to indicate that the two are completely equivalent:

Programming in Lua, first edition said:
That is, all tables are created equal; constructors only affect their initialization.
http://www.lua.org/pil/3.6.html
Agoldfish #4
Posted 29 October 2013 - 11:01 AM
It seems like you made this after you told me how to use tables :3. Anyway, nice tutorial, might come in handy sometime.
H4X0RZ #5
Posted 29 October 2013 - 05:39 PM
Good tutorial, but:

local tbl = {["foo"]="bar"}

-------------------------
--This
print(tbl["foo"])
--Is not the same as
print(tbl.foo)
-------------------------
--To do the second type you have to do it like this
local tbl = {foo = "bar"}
print(tbl.foo)
:D/>
MudkipTheEpic #6
Posted 29 October 2013 - 05:45 PM
Good tutorial, but:

local tbl = {["foo"]="bar"}

-------------------------
--This
print(tbl["foo"])
--Is not the same as
print(tbl.foo)
-------------------------
--To do the second type you have to do it like this
local tbl = {foo = "bar"}
print(tbl.foo)
:D/>

Misinformation.

It works either way.
H4X0RZ #7
Posted 29 October 2013 - 07:31 PM
Good tutorial, but:

local tbl = {["foo"]="bar"}

-------------------------
--This
print(tbl["foo"])
--Is not the same as
print(tbl.foo)
-------------------------
--To do the second type you have to do it like this
local tbl = {foo = "bar"}
print(tbl.foo)
:D/>/>

Misinformation.

It works either way.
o.O
Since when?
I never saw it…

Sorry for the missinformation BTW…
theoriginalbit #8
Posted 29 October 2013 - 07:40 PM
o.O
Since when?
I never saw it…
Since always. The dot notation is just syntactical sugar. The only time it doesn't work is in this case

local t = {["some key"] = true}
print(t.some key) --# this doesn't work, just like the next line doesn't work
t = {some key = true} --# they follow the same rule pattern
theoriginalbit #9
Posted 29 October 2013 - 07:41 PM
o.O
Since when?
I never saw it…
Since always. The dot notation is just syntactical sugar. The only time it doesn't work is in this case

local t = {["some key"] = true}
print(t.some key) --# this doesn't work, just like the next line doesn't work
t = {some key = true} --# they follow the same rule pattern

What you're thinking is that THESE aren't the same

local var = "hello"
local t = {}
t[var] = true --# adds true under the key "hello"
print(t.var) --# looks for a key "var"
which they are not the same.
Symmetryc #10
Posted 29 October 2013 - 08:11 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:

myTable[{}] = 5
myTable[true] = 10
theoriginalbit #11
Posted 29 October 2013 - 08:15 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:

myTable[{}] = 5
Of course hoping that you save the table so that you can access it later!

local k = {}
local t = {[k] = "tables as keys!"}
print(t[k])
Symmetryc #12
Posted 29 October 2013 - 08:22 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:

myTable[{}] = 5
Of course hoping that you save the table so that you can access it later!

local k = {}
local t = {[k] = "tables as keys!"}
print(t[k])
Well, it depends. Let's say you wanted to just make a table of information that your going to return (you're doing this in a function), the end user will use pairs/next to get the values, so there is really no functional purpose in saving them, although it does add to the readability (*wink* :P/> *wink*).
MudkipTheEpic #13
Posted 29 October 2013 - 09:37 PM
-snip-
Sorry for the misinformation BTW…

It's OK, everyone makes mistakes.
Zudo #14
Posted 30 October 2013 - 02:13 AM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:

myTable[{}] = 5
myTable[true] = 10

I put that in the first part.
Symmetryc #15
Posted 30 October 2013 - 01:52 PM
You can actually use almost any value as a key in a table, not just strings and numbers, so this will work:

myTable[{}] = 5
myTable[true] = 10

Anyway, it is really stupid to use boolean and tables as well.
I hope you were kidding.
LBPHacker #16
Posted 31 October 2013 - 12:46 AM
I put that in the first part. Anyway, it is really stupid to use boolean and tables as well.
Man, that hurt… That was like saying it's stupid to use C++. You can't just go over and state that a bunch of people is stupid, just because they do things you don't.
Zudo #17
Posted 31 October 2013 - 04:00 AM
I put that in the first part. Anyway, it is really stupid to use boolean and tables as well.
Man, that hurt… That was like saying it's stupid to use C++. You can't just go over and state that a bunch of people is stupid, just because they do things you don't.

I'm not saying that people are stupid, I was just saying that using boolean and tables is a bad idea, unless there is actually a good reason for doing it.
Engineer #18
Posted 31 October 2013 - 07:08 AM
You should also explain what happens when you do the following:

local t = {
  x = "random",
  s = "key"
}

local x = t

A hint what you should explain is actually this "strange" behaviour:

x.lol = ":D/>"
print( t.lol )

If you dont understand whats going on there, why have you written this tutorial? 0.o
Kingdaro #19
Posted 02 November 2013 - 02:25 PM
What Engineer demonstrated has actually screwed me up quite a bit when I was developing with LÖVE a while ago, so it'd be good for OP to explain that.
ChemE #20
Posted 20 November 2013 - 10:53 AM
Nice tutorial thanks!
Fedkiv #21
Posted 12 December 2013 - 09:13 PM
since I havent found anything clear enough I want to ask it here now -> how do you exactly use it? I know how to set it up but do you activate it when a SAM is trying to lock you, or after he shoot its missile? And if you really can confuse the missiles with the ECM and you are very low to the ground could the ECM make it crash against the ground?

My English isnt the best but hopefully understandable

Thanks
SuperKomputerKid #22
Posted 08 March 2014 - 01:57 AM
Thanks for sharing!
IsaacTBeast #23
Posted 16 March 2014 - 02:22 AM
How do you execute a table?
theoriginalbit #24
Posted 16 March 2014 - 02:40 AM
How do you execute a table?
I thought you knew Lua? You don't execute a table, in fact you don't 'execute' anything in programming; the term you're probably looking for is 'call' or 'invoke', but in either case you still do neither for a table. A table is a data structure similar to Associative Arrays in other languages, it is simply a place to store information.
Edited on 16 March 2014 - 01:40 AM
CometWolf #25
Posted 16 March 2014 - 10:14 AM
Well technically you could call a table if it has a __call metamethod, but that's probably not very relevant to whatever Issac is doing.
theoriginalbit #26
Posted 16 March 2014 - 10:15 AM
[redacted]
Edited on 16 March 2014 - 09:16 AM
sjones321 #27
Posted 16 March 2014 - 06:40 PM
While it might not have covered everything to do with tables, I still thought this was a very well written introductory tutorial to tables.
MostwantedRBX #28
Posted 19 March 2014 - 08:01 PM
How do you execute a table?
I thought you knew Lua? You don't execute a table, in fact you don't 'execute' anything in programming; the term you're probably looking for is 'call' or 'invoke', but in either case you still do neither for a table. A table is a data structure similar to Associative Arrays in other languages, it is simply a place to store information.

I thought you could do this, if you really wanted to:

MyTable = {
PrintStuff = function(Stuff)
print(Stuff)
end
}
MyTable.PrintStuff("Hello, World!")
That is technically calling a table. ;D

EDIT:
I think this is a great tutorial for beginners, OP. Good going.
Edited on 19 March 2014 - 07:02 PM
CometWolf #29
Posted 19 March 2014 - 08:06 PM
You're calling a function stored in a table, not the table itself. To call a table you'll need a __call metamethod.
theoriginalbit #30
Posted 19 March 2014 - 10:49 PM

MyTable = {
PrintStuff = function(Stuff)
print(Stuff)
end
}
MyTable.PrintStuff("Hello, World!")
That is technically calling a table. ;D
technically that is accessing an entry in a table and then if the entry exists and is a function it invokes said function.
MostwantedRBX #31
Posted 19 March 2014 - 10:58 PM

MyTable = {
PrintStuff = function(Stuff)
print(Stuff)
end
}
MyTable.PrintStuff("Hello, World!")
That is technically calling a table. ;D
technically that is accessing an entry in a table and then if the entry exists and is a function it invokes said function.

Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Edited on 19 March 2014 - 09:59 PM
theoriginalbit #32
Posted 19 March 2014 - 11:03 PM
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows tData(1) (normal brackets means invocation/calling) to work as though you typed tData[1] (square brackets means access)

local tData = setmetatable({"hello", "world"}, {
  __call = function(t, i)
	return t[i]
  end
})
As stated, it allows you do do the following

print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello
Edited on 19 March 2014 - 10:04 PM
MostwantedRBX #33
Posted 19 March 2014 - 11:19 PM
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows tData(1) (normal brackets means invocation/calling) to work as though you typed tData[1] (square brackets means access)

local tData = setmetatable({"hello", "world"}, {
  __call = function(t, i)
	return t[i]
  end
})
As stated, it allows you do do the following

print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello

Ah, I haven't learned to use metatables effectively yet. I'm keeping busy learning other languages, too, like Java, C++ and Python, so I haven't really had the time. It may be worthwhile to do so, though. I shoot from place to place, lol.
apemanzilla #34
Posted 21 March 2014 - 04:48 PM
Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows tData(1) (normal brackets means invocation/calling) to work as though you typed tData[1] (square brackets means access)

local tData = setmetatable({"hello", "world"}, {
  __call = function(t, i)
	return t[i]
  end
})
As stated, it allows you do do the following

print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello

Ah, I haven't learned to use metatables effectively yet. I'm keeping busy learning other languages, too, like Java, C++ and Python, so I haven't really had the time. It may be worthwhile to do so, though. I shoot from place to place, lol.
Meta tables are definitely some of the more powerful abilities of Lua. Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>
theoriginalbit #35
Posted 22 March 2014 - 12:22 AM
Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>
Yeah kinda, the metamethods are considered to be a part of the table however, so by sheer technicality you are correct.
Edited on 21 March 2014 - 11:23 PM
apemanzilla #36
Posted 23 March 2014 - 03:59 PM
Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>/>
Yeah kinda, the metamethods are considered to be a part of the table however, so by sheer technicality you are correct.
I guess it all depends on how technical you want to be :)/>
ncfriend #37
Posted 29 March 2014 - 11:46 AM
When i use lua(), and run a function, it sometimes spits out "table: 2de4a71" (the numbers and letters are random) How do you get verbatim output out of it?

Lol, I suppose. From the computing definitions I've seen from google(Yep, I looked it up), calling is to cause the execution of, and accessing is to obtain, examine or retrieve. :P/>/>
Precisely. Take it from the Software Engineer, the code you've got there is definitely not invoking the table. Here's an example of some (advanced) code that invokes a table to get an index; i.e. allows tData(1) (normal brackets means invocation/calling) to work as though you typed tData[1] (square brackets means access)

local tData = setmetatable({"hello", "world"}, {
  __call = function(t, i)
	return t[i]
  end
})
As stated, it allows you do do the following

print(tData[1]) --# outputs: hello
print(tData(1)) --# outputs: hello

Ah, I haven't learned to use metatables effectively yet. I'm keeping busy learning other languages, too, like Java, C++ and Python, so I haven't really had the time. It may be worthwhile to do so, though. I shoot from place to place, lol.
Meta tables are definitely some of the more powerful abilities of Lua. Technically, even with the code above, you're still not calling the table; you're calling it's __call metamethod. If that makes sense :P/>/>
I haven't ever heard of metatables before, that's cool!
theoriginalbit #38
Posted 29 March 2014 - 11:25 PM
I haven't ever heard of metatables before, that's cool!
Yes metatables are very cool and can allow you to do some very powerful things; I do however suggest not using the code that I posted, while 'cool' it is very bad practise! I just made the code to prove a point :P/>
Edited on 29 March 2014 - 10:26 PM