Tables - A better understanding & perspective on how to use them

Keeping in mind

This is my first Community Tutorial, so if you have anything you’d want to correct me on please reply at your own will!

Tables, we pretty much use them for our everyday ROBLOX uses when programming such as: Storing values for later use, saving player data, and all that stuff! But there may be some instances where we’re confused on how they work; examples such as being:

  • Basics/General Concepts
  • Inserting, Removing, and Finding, variables/objects into a table
  • The difference of what an Array & a Dictionary is
  • Using a function that returns back an array (GetChildren, GetDescendants, etc)

Now you may wonder struggling here:

What is this supposed to be? New stuff that’s really confusing to me, my brain is gonna get fried…

Or:

What? Did I miss a step or something? When do you insert that in & what is it?

But no fret! Sometimes it may take a couple days to fully understand the concept of something new, & if you’ve tried everything you could but to no avail worked, then hopefully this tutorial would help you understand a bit more about what tables really are! So, let’s get started with the basics!

General Idea of a Table

Before we start out with configuring with tables, let’s start with the general idea of what it truly is. Now, when you think of a table…What is the first thing that comes into your mind? Think about it for a moment. Tables could be defined as anything depending on the way you’d wanna look at it. Have you got one? If so, then you can click below to reveal what the answer may be :thinking:

Click to Reveal the Answer

If you said a Lua/Programming table, you’re wrong

On a serious note though, think from a literal standpoint here: Look at this realistic table. Now think about programming tables. What are they both capable of doing? I’ll give a couple examples:

  • They can hold & store objects at any given moment

  • We’re able to access them whenever we want (Take an Object, Place an Object, whatever really!)

Pretty much the same thing right? Just imagine programming tables as you know, real life tables that you can store/put stuff on, and receive them later!

The Developer’s API Reference states that a table is a Lua data type, which can store multiple values (X = 5, where 5 is the value) whether it be a Number, String, Boolean, or even a function!

We’re gonna be looking at 2 types of Tables: Arrays & Dictionaries. We’ll start with Arrays first! To create an Array, we can go ahead and create a script inside our workspace/ServerScriptService and put this:

local Array = {}

print(Array)
--Expected Output: {}

We now have our first array we’ve created!

Wait! What if I want to insert something inside my array? What would I do then?

Well, I was just about to get to that!

Table Functions

Tables have a lot of functions that each serve different purposes, for now though we’ll just look at the main & basic functions members commonly use:

  • table.insert
  • table.remove
  • table.find

All of these should be simple to explain, so let’s go ahead and break this up!

Inserting something into a Table

Probably 1 of the most functions people use, table.insert can be used to insert a value on a specific table. Refer back to the real life table example I gave earlier, think of it like this:

You’re basically placing an object onto the table, whether it be a Water Bottle; Jacket; or even a Banana

Now how would you use this function? There are 3 parameters to keep in mind when using this:

  • (Required) Parameter 1: Needs to be a Table variable of some sort

  • (Optional) Parameter 2: The position (Or index) where to insert the value from inside the table, leaving this blank will place the value at the end

  • (Required) Parameter 3: The value that you want to insert inside the specific table (As referenced in Parameter 1)

If you’re a bit confused on this I understand, so why don’t we go ahead and add some more things onto our script?

Using what we know from table.insert, we can just create another variable called “String” and insert our variable into the table!

local String = "Hello, I am a string!"
local Array = {}

table.insert(Array, String)
print(Array)
--Expected Output: 
{
    [1] = "Hello, I am a string!"
} 

When you insert something in a table, an index will be created as well
An index is pretty much a number that is defined by a certain order that the table goes through

We first put our Array variable in the first parameter, & our String variable in the second (Which should be the third instead!)

But what if you’d wanna place it in a different index when we have multiple things inside the table? Well:

local NewObject = "Banana"
local Array = {"Jacket", "Water Bottle"}

table.insert(Array, 2, NewObject)
print(Array)
--Expected Output:
{
    [1] = "Jacket",
    [2] = "Banana",
    [3] = "Water Bottle"
} 

This time, we added a 2 in Parameter #2 to position/index where we want the value to be in table.insert(Array, 2, NewObject)
Again, the position parameter is completely optional but if you want to organize your table differently then feel free to experiment more on it!

Removing something from a Table

This one will be a bit short, but basically I’ll sum it up with this 1 sentence:

table.remove is basically the opposite of what table.insert is

What do I mean by that? Well, since we just talked about inserting objects, what if we wanted to remove an object from a table? table.remove can do that! It has 2 parameters:

  • (Required) Parameter 1: Needs to be a Table variable of some sort

  • (Required) Parameter 2: The position (Or index) where to remove the value from inside the table

Let’s say we were heading out to go somewhere, it’s pretty cold outside so we’ll need a Jacket :thinking:

local Array = {"Jacket", "Banana", "Water Bottle"}

table.remove(Array, 1)
print(Array)
print("Ah that's better")
--Expected Output:
{
    [1] = "Banana",
    [2] = "Water Bottle"
} 

Since we removed the first index from the table (Which is equal to the string “Jacket”), the table re-organized itself then printed the Banana first, then the Water Bottle second! Using table.remove on the 2nd index would remove the Banana (go back I want to be Monke) string inside the table, and so on & so forth!

Finding something inside a Table

Now that we know how tables work a bit better, what if we want to find a specific value of a table? You may see some people may use table.find when:

  • Creating an Admin List to only give admin to specific players

  • Finding a specific tool inside a Player’s Backpack

Using the table.find function will check inside the table for the specific value in a linear search type of way, if the table.find function couldn’t find anything…It’ll return back as nil, since it didn’t find the specific value

table.find will have 3 parameters:

  • (Required) Parameter 1: The Table variable you’re attempting to find for

  • (Required) Parameter 2: The value you’re attempting to find

  • (Optional) Parameter 3: The specific index where to find the value from

It might sound confusing, but I’ll give a couple of examples:

Alright, I want you to meet someone who will help me with table.find, meet Billy!

Billy: Hi! My name is B-

OK THANK YOU BILLY FOR INTRODUCTING YOURSELF! Now, say Billy has a couple of tools in his Inventory here:

Billy: :slight_frown:

local BillyTools = {"Medkit", "Candy Cane", "Tax Evasion For Dummies"}
local ToolToFind = "Medkit"

local Results = table.find(BillyTools, ToolToFind) 
print(Results)
--Expected Output: 
1

If the tool we’re trying to find is a “Medkit” string, we can use table.find to find what kind of value we’re looking for! If it’s found, then it will print the index of the table! But if we wanted to find the Tool in a specific order? We’d do something like this:

local BillyTools = {"Medkit", "Candy Cane", "Tax Evasion For Dummies"}
local ToolToFind = "Medkit"

local Results = table.find(BillyTools, ToolToFind, 3) 
print(Results)
--Expected Output: 
nil

Now this example here prints out nil, but do you know why? Parameter #3 is trying to find the index’s value “Medkit”, but it’s actually “Tax Evasion For Dummies” so if it can’t be found, nil will be returned! The same goes for this as well:

local BillyTools = {"Medkit", "Candy Cane", "Tax Evasion For Dummies"}
local ToolToFind = "Other Unrelated Tool"

local Results = table.find(BillyTools, ToolToFind) 
print(Results)
--Expected Output: 
nil

We aren’t able to find anything, since our ToolToFind variable is defined as a way different string so that’ll return back as nil as well

Could you use table.find using Conditional Tests?

You actually can! Using the same way we did for table.find, let’s say we go ahead and implement a Admin List of Players:

local AdminList = {"Jackscarlett", "SpecialAdminGuy", "OtherSpecialAdminGuy", "ThatOneToxicAdminThatsApparentlyNotBanned"}

game.Players.PlayerAdded:Connect(function(Player)
    local PlayerName = Player.Name --Here, Player.Name is defined as a string 
    local PlayerGui = Player:WaitForChild("PlayerGui")

    local Results = table.find(AdminList, PlayerName)
    if Results then
        local AdminGUI = game.ServerStorage.AdminGUI:Clone()
        AdminGUI.Parent = Player.PlayerGui
        print("A admin has joined the server!")
    else
        print("A regular member has joined the server!") --This would result as returning back nil if the Player who joined was not part of the "AdminList"
    end
end)

Personally, I just create a variable that’s named Results but back on topic here: The Results variable will check if the table.find function returns back as a valid index, or nil if it’s valid, then we can clone our AdminGui to our specific Player! Otherwise we just implement an else statement so we know that a normal player joined!

Arrays and Dictionaries
(This took me way longer to learn but hopefully I can explain it here)

All of the examples I’ve used before were Arrays, now we’re gonna learn about what Dictionaries are! Dictionaries are also a type of a table as well, & you can use them to define your own key! Now you may ask:

What is the difference between Dictionaries & Arrays?

  • Arrays go in a indexed order, with 1 being the starting position while Dictionaries are capable of you being able to define your indexes whatever order you want!

  • Arrays have numbered indexes & values, while Dictionaries have custom keys to identify values

Code Reference:

--Array:
local Array = {1, true, workspace.Baseplate, "String!"}
--Dictionary:
local Dictionary = {
    A = 10,
    B = 20,
    C = 30,
    D = 50
}

Basically: Dictionaries are your own language of what key you want to name! You must also include a String inside your Dictionary when defining which key you’re looking for

Creating a Dictionary, we can do this:

local JacksDictionary = {
    BeeScript = "According to all known laws of aviation, there is no way a bee should be able to fly."
}
print(JacksDictionary["BeeScript"])
--Expected Output: A dead meme
According to all known laws of aviation, there is no way a bee should be able to fly.

A dictionary’s key can basically be anything you want, whether it be a Player’s Stats or a Customer’s Order you wanna take!

Like arrays, we can also make multiple keys as well:

local JacksDictionary = {
    BeeScript = "According to all known laws of aviation, there is no way a bee should be able to fly.";
    NumberOfBees = 10;
    MakeHoney = false;
}

print(JacksDictionary["NumberOfBees"])
print(JacksDictionary["MakeHoney"])
--Expected Output: 
10
false

But if I recall, the keys in Dictionaries will be unordered since you’re custom-indexing each of their names :thinking:

But how would we remove/insert keys in Dictionaries?

Well, what we can do it to remove something inside our Dictionary is change our keys equal to nil!

local JacksDictionary = {
    BeeScript = "According to all known laws of aviation, there is no way a bee should be able to fly.";
    NumberOfBees = 10;
    MakeHoney = false;
}

JacksDictionary["BeeScript"] = nil

print(JacksDictionary["BeeScript"])
--Expected Output: 
nil

For inserting something, we can create a string inside our Dictionary like so:

local JacksDictionary = {
    BeeScript = "According to all known laws of aviation, there is no way a bee should be able to fly.";
    NumberOfBees = 10;
    MakeHoney = false;
}

JacksDictionary["NewKey"] = "Hello! I am a new key!"

print(JacksDictionary["NewKey"])
--Expected Output: 
Hello! I am a new key!

What if I have a custom key that takes the place of a number?

Well, you can encase those in brackets! Not encasing them would result in an error, since the Dictionary is trying to figure out if the number is an array index, or a dictionary key

local NumberedDictionary = {
    [20] = "This is the number 20!";
    [7500] = workspace.Baseplate;
    [1000000] = "Boss Health" --MATE IS THIS A DARK SOULS BOSS?
}

print(NumberedDictionary[1000000])

--Expected Output:
Boss Health

Using GetChildren()/GetDescendants()

We’re approaching the last sections of our tutorial, and lastly we’re gonna learn about how to use the GetChildren() & GetDescendants() functions that will return Arrays! firstly, let’s talk about what GetChildren() does:

GetChildren() will get all of Instance A’s children, & will return back an array of all the Instances inside Instance A

How could you use it then in your scripting? Say I have 4 Parts in a folder in the workspace: Part, Part2, and Part3, and say I insert Part4 inside Part2:

image

local FolderStuff = workspace.PartFolder:GetChildren()
print(FolderStuff)

--Expected Output:
{
    [1] = Part,
    [2] = Part2,
    [3] = Part3
}

Now you may have noticed something:

Why didn’t Part4 get printed out?

That’s because we only got the Children (Or objects) inside that folder, but not it’s Descendants inside the Folder (Aka the Children inside the Children inside the Children and so on, CHILDREN-CEPTION MOMENT)

We could also do this numerically by using getting the length of the table like so:

local FolderStuff = #workspace.PartFolder:GetChildren()
print("Parts inside the Folder's Children: "..FolderStuff)

--Expected Output:
"Parts inside the Folder's Children: 3"

Since there are 3 Parts inside the Folder’s Children, we can use the # operator to get the length of the table which results as: 3!

Next up is GetDescendants(), now you may have an idea as to what this one will do…But I’ll ask the question anyways:

What is the difference between GetDescendants() & GetChildren()?

Similar:

  • GetChildren() & GetDescendants() both return Arrays

Different:

  • GetChildren only gets the Instance’s Children & stops there, while GetDescendants() will get every child of the object whether if they’re parented inside or not

Again, refer to the PartFolder image:
image

Part4 is parented to Part2, so using our same sample codes here we can do this:

Array Example:

local FolderStuff = workspace.PartFolder:GetDescendants()
print(FolderStuff)

--Expected Output:
{
    [1] = Part,
    [2] = Part2,
    [3] = Part4,
    [4] = Part3
}

Numeric Example:

local FolderStuff = #workspace.PartFolder:GetDescendants()
print("Parts inside the Folder's Descendants: "..FolderStuff)

--Expected Output:
"Parts inside the Folder's Descendants: 4"

They basically both do the same thing, just that GetChildren() only gets the Children of that object while GetDescendants()GETS EVERYTHING INSIDE THE OBJECT

The End
If you’ve managed to read the entire thing, then congratulations! You’ve learned about the basic & general concepts on how you could use tables, learning table functions (table.find, table.insert, table.remove), differences between Arrays & Dictionaries + Understanding how they work, and using certain functions that returns tables! I hope you enjoyed it, & if there’s anything I should change please feel free to reply! :smile:

72 Likes

Dont know how I’m the first one to reply to this!

But anyways,
This is really the only post in here I have seen that uses the examples that somebody would actually use!

For example, I’m using tables to return if parts are touching, using a build ion roblox function that uses… tables!
Sorry for the uncliped video here, was kinda doing it fast. Also ignore the overlapping audios, windows 11 is bad and there’s an invisible search prompt RIGHT OVER THE MUTE BUTTON :frowning:
But anyways, here’s the example.

(i caught the tree at a bad time, this is the working version.
image

This is a more… complicated way of using tables.

--touching is somewhere above in the code
local touching = false
local function CheckTouch(mod)
	local selpart = mod
	if mod:IsA("Model") then
		selpart = mod.PrimaryPart
	end
	local CP = selpart.Touched:Connect(function() end)
	local collpts = selpart:GetTouchingParts()
	touching = false
	for i = 1, #collpts do
		if not collpts[i]:IsDescendantOf(mod) and i ~= game.Workspace:WaitForChild("Plots"):FindFirstChild(game.Players.LocalPlayer.Name.."'s Plot")  then
			touching = true
			break
		end
	end
	CP:Disconnect()
end

That, checks if the part is touching, IF it isn’t a descendant of the model, and it isn’t the plot.

Like 700 lines later we have this

			if not Part:FindFirstChildWhichIsA("SelectionBox") then 
				local SB = Instance.new("SelectionBox")
				SB.Parent = Paart
				SB.Adornee = Paart
				SSB = SB
				SB.Name = "SelectionBox"
			end
			CheckTouch(Paart)
			if touching == false then
				SSB.Color3 = Color3.new(0.129412, 1, 0.419608)
				CanPlace = true
			else
				SSB.Color3 = Color3.new(1, 0.270588, 0.282353)
				CanPlace = false
			end

Deeper i have something like

if not touching then
--Placement code--
else
--Trash code with errors, sounds, and broken code
return 
end

That’s really an overcomplicated version of tables, and built in Roblox functions of code.

Don’t know why I typed this, but it’s now here.
Thanks for reading it all!
i checked for burnt bacon in the code while making it, yw

4 Likes

There are tons of different ways on using tables, whether it being checking on which areas you can place Parts on, whether to loop through all Objects & checking which ones you want, and etc etc

I just mostly keep it simplistic so that others can fully understand the concept behind how they truly work, but once you start to learn more & more about it you can start to further develop into the more general idea of tables & understand other tutorials made by this community :slightly_smiling_face:

3 Likes

What about pairs and ipairs. They’re used for getting all elements in a table too.

True, but that’s just if you want to loop through an entire table of objects really

I just broke it down at the start to begin with in the first place to use the proper table functions for them, of course there are alternatives but I just went with the functions that tables provide you with