Skip to content

An Introduction to Tables

A table is a way to store multiple values in one variable. Essentially, it is a list in which each item has 2 parts: (1) a key (also called an index), which is the name of the item, a way to tell the table which thing you want to look at; and (2) the value, which is the actual data. As an example of how something simple to say can be complex and confusing to understand: both the key and the value can be any valid Lua value but nil… usually. We’ll cover the nil value in a different lesson. It’s weird enough that you can use, as key, value or both, strings, objects, and even other tables! Craziness. Not all languages can do that, but throughout this course you’ll not only make sense of it, but learn some awesome Code Fu moves to do amazing things with it. Let’s start at the beginning.

Arrays

An array is probably the most straightforward and easily understood kind of table. It is, in short, a list. Each list item, called a row or record in the table, has as its key a whole number. The first row’s key is 1, the next is 2, and so on. (You will sometimes hear someone refer to such a list as one-indexed, meaning that the beginning of the list is identified as item 1. A zero-indexed list or array begins its numbering with 0. That happens a lot in some languages, but not much in Lua.) If you stick a row into the middle of the list, the higher numbers will bump up one, and removing a row causes others to shift down and fill the gap. We’ll try out all this shortly. But first, we need to make the table!

Creating Tables

The fastest way to declare a table is by assigning a variable name to an empty pair of curly brackets:

myTable = {}

That makes a table that starts off empty. If you want, a list of values can be specified when you create the table:

myTable = {“here we go”, “there we go”, “arm in arm together”}

This starts our table off with 3 values, and because we didn’t tell it what to use for each value’s key, it automatically assigns whole numbers for them, starting with 1, in the order they were listed. This brings us to the other way of assigning initial values to a table, which is to tell it what you want for each key as well as each value. This is what it looks like when you do that with the table we just made:

myTable = {[1]=”here we go”, [2]=”there we go”, [3]=”arm in arm together”}

As you might expect, if you’re telling it what goes with what, you don’t have to put them in order. This declaration will make exactly the same table as the previous 2 examples:

myTable = {[3]=”arm in arm together”, [2]=”there we go”, [1]=”here we go”}

But right now we’re just working with arrays, for which we don’t need extravagant declarations. Let’s get back to them.

The square brackets, used in the last 2 examples to indicate which row you want to assign a value to, are also used to reference (meaning, to refer to, to talk about) a given row in a table. If the above table was in a script, the command print(myTable[2]) would cause an output of there we go. It indexes (goes to) the row identified by the number 2 and prints the value stored therein. If you decided you wanted something else in that row, perhaps the number 6, you would say myTable[2] = 6 and it would suddenly be so. Changing data types doesn’t give it any trouble, nor does getting the value from another variable. And each row of the table can be of a totally different data type than the others. Effectively, each row in a table is a variable of its own, and you can treat it like you would any other variable. Enter the following script and consider its output:

latervar = “this is a new value” -- We’ll keep this for later.
valTab = {“oldvalue1”, “oldvalue2”, “oldvalue3”} -- set up a table with a few values
print(“Before changing it, the 3rd row’s value is “,valTab[3])
valTab[3] = valTab[1] -- Make the 3rd value equal the 1st value
print(“After changing it, the 3rd row’s value is “,valTab[3])
print(“Before changing it, the 2nd row’s value is “,valTab[2])
valTab[2] = latervar -- Make the 2nd value equal another variable
print(“After changing it, the 2nd row’s value is “,valTab[2])

You’ll recall that in the last lesson, you used the # sign to identify how many items there were in the list of child objects for your model. This is called the # operator (“pound operator”) or length operator. It indicates the number of rows in a table. Note that it only counts number-indexed rows, so when we move on to using other things, it won’t cover that. Add this to the end of your script and run it again:

print(“There are “, #valTab, ” rows in this table.”)

The number it comes up with is 3, of course, but it’s gratifying to see it actually work. It’s easy to follow that up with a for loop similar to the one we used last lesson:

for x = 1, #valTab do
       print(“Key: “, x, “, Value: “, valTab[x])
end

Stringing Strings

Time to pause our exploration of tables and look at a very useful concept, concatenation. Concatenation means attaching strings (which you’ll recall are letters, numbers, and other characters grouped into a single value and defined by putting quotes around them) one to another, to give a longer string. You already know that you can do something like that when printing, by listing the things you want printed as comma-separated parameters of a print function. It simply puts one right after the other. But what if you want to do that outside the print function, perhaps to store the result in a variable? For that, you use the…

Concatenation Operator

Concatenation is the operation of joining two strings together, and the operator is two periods: .. To use it, place it between the values you want to join. Like most operators, you can use it multiple times in an expression, so for example, the following command is perfectly valid:

longerString = “Some sentences ” .. “can run a bit” .. ” longer than others, but we ” .. “like it that way.”

Note that one way or another, I included spaces in the string literals so that the words were separated in the final value of longerString. If you don’t, there won’t be any – which can be what you want, at times. The expression “concat” .. “enation” will give the value “concatenation” without any extraneous spaces. Variables can be used as well:

m = “John Galt”
mysteryMan = “Who is ” .. m .. “?”
print(mysteryMan)

Now, while you can’t concatenate just any value with any other, you can use numbers as well as strings. Try out the following little script – but in this case, be sure to copy and paste it, changing nothing but (if needed) correcting the quotes!

testing = “I would like ” ..50.. ” dollars, please.”
print(testing)

Uh, oh. Didn’t I just say you could do that? It turns out there’s a quirk in Lua’s formatting that will give you an error if you try to concatenate numbers along with strings, but only if there’s no space after the number. Put a space after the 50 and before the .. and try it again.

There we go! Once the quirk is appeased, what happens is that the operator converts the numeric value into a string value in order to include it. I suggest using variables for this sort of thing when you can, to avoid the risk of that error.

As you might suspect, using numbers can give some interesting results, and you’ll want to pay attention to how you use it. Done cleverly, you can do some interesting operations. Consider the output of the following script, which also demonstrates that you can do concatenation directly within a print command:

print(110 + 100 + 011)
print(110 .. 100 + 011)
print(110 + 100 .. 011)
print(110 .. 100 .. 011)

Method: table.concat()

It may be fairly obvious to you that you could use concatenation with a for loop to print out the contents of a table all at once. Something like this would do:

tableToPrint = {“Sunday”, “Monday”, “Tuesday”, “Wednesday”} -- a table
fullString = “The Days Are: ”
for c = 1, #tableToPrint do -- for each row…
       fullString = fullString .. ” ” .. tableToPrint[c] -- …add its value to a string
end
print(fullString) -- Let’s see the whole thing!

However, there is a very useful item called the table library, which contains a more compact and very flexible way to do this with arrays: table.concat() (The dot-notation indicates that concat() is a method of an object called table, which you may well have guessed. We’ll go more into what that means in a later lesson.) The syntax for this function is as follows:

table.concat(t[, s[, b[, e]]])

All those square brackets in the syntax definition just mean (as they did with the for loop syntax definition) that the the later parameters are optional, but to use them you can’t skip any of the earlier ones. t is the table that contains the values you want to concatenate. s is a string that will separate (go between) each item concatenated, like I did with a space in the example above. If left out, there will be nothing between them. b is the row to begin concatenation. If left out, the default is 1, meaning it starts at the beginning. e is the ending item to concatenate, much like the e parameter in the for loop syntax. If left off, it goes until it reaches the last row of the table.

As usual, this may be easier to grasp in practice. Enter the following in a script in your Roblox world, and run it:

tab = {“I”, “am”, “going”, “crazy”, “about”, “Lua”}
print(table.concat(tab, ” “)) -- space between each value
print(table.concat(tab, “:^D”)) -- silly face between each
print(table.concat(tab)) -- nothing between each
print(table.concat(tab, ” “,1,4)) -- first 4 rows only
print(table.concat(tab, ” “,4)) -- starting at 4th row

This only really works if all the values are strings or numbers. Using other data types, as we will begin to do in a couple lessons, will not give you any normal output. Also, if b is larger than e – that is, if it’s told to start after the row it’s told to end with – the function will return an empty string. Try print(table.concat(tab, ” “, 4,3)) in the above example if you want to see it (not) happen.

Method: table.insert()

To insert a row into an array, use table.insert(). Its syntax looks like this:

table.insert(t, [p, ] v)

t is the table to insert a row into. p is the position the new row will occupy, meaning that the value of p will be its key. v is the value inserted. It doesn’t overwrite anything in the table: anything already there (or above) gets shifted up to make room. The square brackets in the syntax definition indicate that the position argument is optional. If you leave it out, it will put the new row at the end of the table.

Let’s look at the method which removes a row, and then we’ll try them both out.

Method: table.remove()

The syntax for table.remove() looks like this:

table.remove(t, [p])

They just keep getting simpler, don’t they? As with table.insert(), t is the table to remove the row from, and p is the position of the data to delete. Like table.insert(), this function is designed for arrays, and will move the higher-indexed rows down one to “close the space,” if you will, and maintain a continuous series of numeric keys in the table. If the position argument is left out, it will remove the last row in the table.

Time to use all 3 table library methods in 1 script!

days = {“Sunday, “Monday”, “Tuesday”, “Wednesday”, “Thursday”, “Friday”, “Saturday”}
print(“A normal week: “, table.concat(days, “, “))
table.remove(days, 6)
print(“An altered week: “, table.concat(days, “, “))
table.insert(days, 6, “Pippinday”)
print(“My week: “, table.concat(days, “, “))
table.remove(days, 2)
table.insert(days, “Saturday II”)
print(“An awesome week: “, table.concat(days, “, “))

There weren’t any Messing With Blocks exercises in this lesson, but there will be for the next one. You’re going to be using tables for many things in the future, and blowing people’s minds with what you do with them. This is just the bare beginning.