Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
✓ ANSWER ACCEPTED

Can a Vector2 Value be used as a key for a table?

The roblox wiki says "The key column is used to find a row in the table, and the value is the value that is stored in that row. Both the key and value can be any Lua value (numbers, strings, Parts etc., and even other tables) except nil. Lua tables do not have to use either numbers, strings or tables as keys. Any combination of key types can be used." (http://wiki.roblox.com/?title=Table). However, when I test this out in the output, a vector2 value doesn't work.

> mytable = {}
> mytable[Vector2.new(1,0)] = 5
> print(mytable[Vector2.new(1,0)])
nil

I don't necessarily need a Vector2 value specifically, but I need to be able to have 2 different "inputs" for the key. I have tried the same thing as mytable[{1,0}] = 5, but it still returns nil.

1 comment

1

Maybe consider using strings? print(mytable[vec2(1,0)]), where vec2() converts the given parameters into the format '%d,%d'.

2 answers

✓ Accepted answer

#What's the problem? Like what @BlackJPI said, when you say Vector2.new() you're creating a brand new and totally different vector value so Vector2.new() ~= Vector2.new(). To solve this make the Vector2 a variable and you can access the X and Y values later like so:

Variable.X
Variable.Y

#Final Product

local mytable = {}
local Vec2 = Vector2.new(1,0)
mytable[Vec2] = 5
print(mytable[Vec2])

5


Hope it helps!

Yes, you can use it as a key, but it will not mean what you think it means.

When key values are tables, they are looked up by reference. Thus, the following totally works:

local a = Vector2.new(5.9, 2.1)
local b = Vector2.new(1.3, 7.6)
local c = Vector2.new(1, 1)

local t = {}
t[a] = 5
t[b] = 8
t[c] = 9
print(t[a], t[b], t[c]) --> 5 8 9

The problem is that just because two Vector2s have the same x and y does not mean they are they same object.

Imagine we weren't using Vector2s, but tables:

local a = {x = 1, y = 1}
local b = {x = 1, y = 1}

local t = {}
t[a] = 5
print(t[b]) --> nil

Why do we get nil? Well, because a and b happen to contain the same information now, but later they could change:

b.x = 5
print(t[b]) --> nil (of course! we only have t[{x =1, y = 1}] in here!)

a.x = 2
print(t[a]) --> 5 --> because `a` is still the same object!

Thus two objects are only truly equal if they change in exactly the same ways.

Lua doesn't know that Vector2s can't be changed, so it cannot apply that reasoning to map them to the same object.

Lua doesn't know, but you do!

An easy (though somewhat cumbersome) way to deal with this problem in general is to turn the objects into strings.

Two Vector2s with the same representation as a string represent the same point in space; and we don't have the problem we have with strings that we do with tables:

local a = Vector2.new(1, 1)
local b = Vector2.new(1, 1)

local t = {}
t[tostring(a)] = 5
print(t[tostring(b)]) --> 5

You can use metamethods to make this process automatic for you:

local backing = {}
local t = setmetatable({}, {
	__index = function(_, key)
		return backing[tostring(key)]
	end,
	__newindex = function(_, key, value)
		backing[tostring(key)] = value
	end
})

local a = Vector2.new(1, 1)
local b = Vector2.new(1, 1)
t[a] = 5
print(t[b]) --> 5!

Multidimensional Arrays

If you're truly storing a grid of points, it may be useful to just use an array-of-arrays (commonly referred to as a "2D array"):

local grid = {}
for i = 1, 10 do
	grid[i] = {}
	for j = 1, 100 do
		grid[i][j] = 0
	end
end

print(grid[5][18]) --> 0
grid[6][20] = 10
print(grid[6][20]) --> 10

This discussion is preserved as it was. New answers, comments, and votes are closed.