---
title: "Tables"
url: /docs/en-us/luau/tables
last_updated: 2026-06-10T23:09:06Z
description: "Data type which can store multiple values of any non-nil type, including booleans, numbers, strings, functions, and other tables."
---

# Tables

The **table** data type can store multiple values of any type that isn't `nil`, including [booleans](/docs/en-us/luau/booleans.md), [numbers](/docs/en-us/luau/numbers.md), [strings](/docs/en-us/luau/strings.md), [functions](/docs/en-us/luau/functions.md), and other tables. Construct tables with curly braces (`{}`):

```lua
-- Construct an empty table assigned to variable "t"
local t = {}
print(t) -- {}
```

You can use a table as an [array](#arrays) or [dictionary](#dictionaries). Arrays use an ordered list of numbers as indices, but dictionaries can have numbers, strings, and objects as indices.

For more information on built-in functions for working with tables, see the `Library.table` library.

## Arrays

An **array** is an ordered list of values. Arrays are useful for storing collections of data, such as a group of players with special permissions.

### Create arrays

To create an array using a Luau table, declare the values in sequential order, separated by commas.

```lua
-- Construct an array with three items
local testArray = {"A string", 3.14159, true}
print(testArray)
```

### Read from arrays

To read from an array, add a pair of square brackets after its reference and specify the index number of the element inside (`[pos]`):

```lua
-- Construct an array with three items
local testArray = {"A string", 3.14159, true}

print(testArray[1]) -- A string
print(testArray[2]) -- 3.14159
print(testArray[3]) -- true
```

> **Warning:** Unlike some languages, Luau uses 1-based indexing for arrays, so the first item in the array is `[1]`, not `[0]`.
### Write to arrays

To define or rewrite the value of an array at an index, declare the index number in square brackets (`[index]`) followed by `=` and the value:

```lua
local testArray = {"A string", 3.14159, true}

testArray[2] = 12345
testArray[4] = "New string"

print(testArray[2]) --12345
print(testArray[4]) -- New string
```

### Iterate over arrays

To iterate over an array, you can use a `for` loop. Because the arrays have numerical indices, you can also use a numeric `for` loop from `1` to the length of the array (`#array`).

```lua
local testArray = {"A string", 3.14159, true, "New string"}

-- Loop using general iteration
for index, value in testArray do
	print(index, value)
end

-- Iterate using the array length operator (#)
for index = 1, #testArray do
	print(index, testArray[index])
end
```

### Insert items

There are two built-in ways to insert an item to the **end** of an array:

- Pass a reference to the array and the item value to Luau's `Library.table.insert()` function.
- Add the new item to the array using the `array[#array+1]` syntax.

```lua
local testArray = {"A string", 3.14159}

table.insert(testArray, "New string")
testArray[#testArray+1] = "Another new string"

print(testArray[3]) -- New string
print(testArray[4]) -- Another new string
```

To insert an item between the start and end of an array, include a position value as the second argument of `Library.table.insert()`. This inserts the new item and pushes the following items up one index position.

```lua
local testArray = {"First item", "Next item"}

table.insert(testArray, 2, "NEW ITEM #2")

print(testArray[1]) -- First item
print(testArray[2]) -- NEW ITEM #2
print(testArray[3]) -- Next item
```

### Remove items

To remove an item from an array, use `Library.table.remove()`. This removes the item at the specified position and moves any following items back one index position.

```lua
local testArray = {"First item", "Next item", "Last item"}

table.remove(testArray, 2)

print(testArray[1]) -- First item
print(testArray[2]) -- Last item
```

## Dictionaries

Dictionaries are an extension of arrays. Dictionaries store a set of key-value pairs, where the keys can be any number, string, or object.

### Create dictionaries

To create a dictionary table, define each **key** followed by `=` and the **value**. Separate each key-value pair with a comma:

```lua
local testDictionary = {
	fruitName = "Lemon",
	fruitColor = "Yellow",
	sour = true
}
```

The keys for dictionaries can be numbers, strings, and objects. For example, a key may also be an `Class.Instance`. To use objects as keys, declare the key in square brackets (`[key]`):

```lua
local part = Instance.new("Part")

local testDictionary = {
	partType = "Block",
	[part] = true
}
```

### Read from dictionaries

To read from a dictionary, add a pair of brackets after its reference and specify the key name. Directly reference a string key using either (`["key"]`) or (`.key`), or instead use a variable value (`[key]`).

```lua
local part = Instance.new("Part")

local testDictionary = {
	partType = "Block",
	[part] = true
}
-- Include quotes for string keys
print(testDictionary["partType"]) -- Block
-- Or use . to index string keys without spaces
print(testDictionary.partType) -- Block
-- Omit quotes for non-string keys
print(testDictionary[part]) -- true
```

### Write to dictionaries

To define or rewrite the value of a new or existing dictionary key, declare the key name in brackets (`[key]`) or, if the key is a string, use (`.key`) followed by `=` and the value:

```lua
local testDictionary = {
	fruitName = "Lemon",
	sour = true
}

-- Change value of existing keys
testDictionary["fruitName"] = "Cherry"
testDictionary.sour = false

-- Insert new key-value pair
testDictionary.fruitCount = 10

print(testDictionary.fruitName) -- Cherry
print(testDictionary.sour) -- false
print(testDictionary.fruitCount) -- 10
```

### Iterate over dictionaries

To iterate over a dictionary, use a `for` loop:

```lua
local testDictionary = {
	fruitName = "Lemon",
	fruitColor = "Yellow",
	sour = true
}

for key, value in testDictionary do
	print(key, value)
end

--[[ Resulting output:
fruitName Lemon
sour true
fruitColor Yellow
]]
```

### Remove key-value pairs

To remove or erase a key-value pair from a dictionary, set its value for a key to `nil`.

```lua
local testDictionary = {
	fruitName = "Lemon",
	fruitColor = "Yellow",
	sour = true
}

testDictionary.sour = nil

for key, value in testDictionary do
	print(key, value)
end
--[[ Resulting output:
fruitName Lemon
fruitColor Yellow
]]
```

## Tables as references

If you store a table in a new variable, Luau doesn't create a copy of that table. Instead, the variable becomes a **reference**, or pointer, to the original table. Any reference to a table reflects any changes to the original table:

```lua
local originalArray = {10, 20}

local arrayReference = originalArray

print("Original:", originalArray[1], originalArray[2])
print("Reference:", arrayReference[1], arrayReference[2])

-- Change values in original array
originalArray[1] = 1000
originalArray[2] = 2000

print("Reference:", arrayReference[1], arrayReference[2])

--[[ Resulting output:
Original: 10 20
Reference: 10 20
Reference: 1000 2000
]]
```

## Clone tables

### Shallow clones

To copy a table without any nested tables, Luau offers the `Library.table.clone()` method.

```lua
local original = {
	key = "value",
	engine = "Roblox",
	playerID = 505306092
}

local clone = table.clone(original)
```

### Deep clones

To copy a more complex table with nested tables inside it, you'll need to use a recursive function similar to the following:

```lua
-- The function used for deep cloning a table
local function deepClone(original)
	-- Define the new table for the copy
	local clone = table.clone(original) 

	-- Loop through the original table to check for table values
	-- If a table is found as a value, deep clone it to the key (index)
	for key, value in original do
		if type(value) == "table" then
			clone[key] = deepClone(value)
		end
	end

	-- Return the finalized copy of the deep cloned table
	return clone
end
```

With the function in place, you can make a deep copy as follows:

```lua
local original = {
	key = "value",
	playerInfo = {
		playerID = 505306092,
		playerName = "PlayerName"
	},
	otherInfo = {
		{
			{1, 3, 5, 7, 9}
		}
	}
}

local clone = deepClone(original)
```

## Freeze tables

Freezing a table makes it read-only, which is useful for creating constant values that you don't want to change. Freezing is permanent; there's no "unfreeze" or "thaw" method. To check if a table is frozen, use `Library.table.isfrozen()`.

### Shallow freezes

To freeze a table without any nested tables, Luau offers the `Library.table.freeze()` method.

```lua
local target = {
	key = "value",
	engine = "Roblox",
	playerID = 505306092
}

table.freeze(target)
target.playerID = 1 --> attempt to modify a readonly table
```

### Deep freezes

To freeze a more complex table with nested tables inside it, use a recursive function similar to the following:

```lua
local function deepFreeze(target)
	-- Shallow freeze the table
	table.freeze(target)

	-- Check each key of the table and freeze it if it's a table
	for _, value in target do
		-- Make sure the value isn't frozen; if it already is, an error will occur
		if type(value) == "table" and table.isfrozen(value) == false then
			deepFreeze(value)
		end
	end
end
```

With the function in place, you can deep freeze a table as follows:

```lua
local target = {
	key = "value",
	playerInfo = {
		playerID = 505306092,
		playerName = "PlayerName"
	},
	otherInfo = {
		{
			{1, 3, 5, 7, 9}
		}
	}
}

deepFreeze(target)
target.playerInfo.playerID = 1 --> attempt to modify a readonly table
```