3D Arrays in Lua?

In C# you can just do [ , , ] or [][][] to create a 3D array, how would you do this in Lua though?

2 Likes

Its basically the same thing, and you can just keep going

somecooltablename["aaa"]["aa"][1] = "yo"

Refer to this post, more informational :stuck_out_tongue:

7 Likes

beat me to it

check out Multidimensional Tables

3 Likes

This doesn’t work

local thing = {}
thing[1][2][4] = "bla"

image

Ah yeah, problem is trying to index it before it has that index. Since you are trying to index the second one ("[2]", it sees there is nothing in the first index to begin with

In order to initialize those, its kind of easier to just see it out like this

local thing = {
	{
		["Cool"] = 
		{
			["A"] = 5;
		};
	}
}

print(thing[1]["Cool"]["A"])
> 5

Sorry for the lack of information in the first post :stuck_out_tongue:
You can still do

local cooltable = {}
cooltable["aa"] = 5
cooltable["aa"]["what"] = 25

since you aren’t trying to index something that isn’t there

4 Likes

adding on to what @Dapale said, say you wanted to make a 2x2 matrix, it’d be like this:

local matrix = {
    {1,2};
    {3,4};
}

There you go! matrix[2][1] would be 3

Now you simply carry to the 3rd dimension. Say we wanted a 1x2x3 matrix:

local matrix = {

    { -- x component

        { -- y component

            1; -- z component
            2;
            3;

        };

        {4,5,6};

    };

}

Now, matrix[1][2][1] would be 4.

Hope I helped in the slightest :+1:

5 Likes

As other people have said you can absolutely nest tables in Lua, which is in effect making a 3D array. You may want to use metatables to take the work off of you defining all the dimensions though.

2 Likes

You can achieve this automatically through __newindex and __index with metatables, as mentioned above:

local dimensionalTable = {}

dimensionalTable.__index = function(table, index)
	if rawget(table, index) == nil then -- if the index doesn't exist, it's made into a new table
		rawset(table, index, setmetatable({}, dimensionalTable)) -- the new table has its metatable set to dimensionalTable so that it is also a dimensionalTable
	end
	warn("table now has index " .. index .. " as a new dimensional table")
	-- i'd recommend keeping this warn for debugging purposes because if you mistype an index, it'll be a table instead of erroring and telling you that the index is nil
	return rawget(table, index)
end

--[[dimensionalTable.__newindex = function(table, index, value)
	rawset(table, index, value)
end]]

dimensionalTable.new = function()
	return setmetatable({}, dimensionalTable)
end

local thing = dimensionalTable.new()
thing[1][2][4] = "bla"
print(thing[1][2][4]) --> prints bla

You may want to make dimensionalTable its own module so that you can access it from any script using require().

Edit: You don’t actually need the __newindex metamethod

9 Likes

Just want to note that if anyone is attempting to send the dimensionalTable between the server and client using RemoteEvents/Functions, you’ll run into trouble because it is a metatable. In other words, the dimensionalTable won’t transfer properly unless you want to do some extra work. If you know the size of your array, this should work:

local array = {}
for x = 1, xMax do
	array[x] = {}
	for y = 1, yMax do
		array[x][y] = {}
		for z = 1, zMax do
			array[x][y][z] = --[insert data here]
		end
	end
end
2 Likes

For most use cases I can think of, metatables are overkill. You can simply define a function to build a 3D array of a fixed size for you, and not have to deal with metatables at all;

local function new3DArray(sizeX, sizeY, sizeZ, defaultValue)
    local array = table.create(sizeX)
    for x=1, sizeX do
        local subArray = table.create(sizeY)
        for y=1, sizeY do
            subArray[y] = table.create(sizeZ, defaultValue)
        end
        array[x] = subArray
    end
    return array
end

Much easier to understand, much less complex, much more performant. You do lose the advantage of infinite size, but that’s not often useful (all your indices in this case must be between 1 and sizeX/Y/Z)

4 Likes

Thanks,

I did figure out what was wrong with my code

local array2D = require(game.ReplicatedStorage.Modules.Array2D)
local newArray = array2D.new(8,8,0)
local count = 64 – Populate array from 64 to 1

for x = 1, 8 do
for y = 1, 8 do
newArray:Set(x,y, count)
count = count - 1
end
end
print(newArray)