Can we use table as key for dictionary?

Can we use table as key for dictionary?

This does not seem to work?

local K = {
	[{"d", 12}] = 6,
	[{"d", 18}] = 4,
	[{"z", 11}] = 12
}

print(K[{"d", 18}]
1 Like

It doesn’t work because they’re different references. When you use {} you’re creating a new table, the only way you could make this work is by for example creating the table in a variable and then using that variable as the key. Just because a table has the same things inside it as another one doesn’t mean it’s the same table.

3 Likes

you cant use tables as keys, instead you can do:

	[6] = {"d", 12}
	[4] = {"d", 18},
	[12] = {"z", 11}
}

print(K[12])

and have the intended effect

1 Like

Yes, you can, but you cannot construct two individual tables that would evaluate to the same due to different memory addresses.

local t = {name = "myname", value = 25}
local dict = {}
dict[t] = "string"

print(dict[t])
3 Likes

I was hoping to be able to use this as a way to fast find a pair inside a dictionary, but I guess I will have to use traditional FOR loop for searching…

Hello.

Yes, you can use tables as keys.

local t1 = {"d", 12}
local t2 = {"d", 18}
local t3 = {"z", 11}

local K = {
    [t1] = 6,
    [t2] = 4,
    [t3] = 12,
}

print(K[t1]) -- Output will be 6

Please, notice that if you try accessing an index in your code, you should use the same reference to the table.

local t1 = {"d", 12}
local t2 = {"d", 12}
print(t1 == t2) -- Will output false

This happens because t1 stores the reference to the first table and t2 the reference to the second table. Although they are identical, you should always keep a reference if you want to find it inside another table.

Best regards,
Octonions

2 Likes

Use a 2D table:

local K = {
    ["d"] = {[12] = 6},
    ["d"] = {[18] = 6},
    ...
}

print(K["d"][12])

Or as an alternative, define the __eq metamethod and use table.find:

do
local mt = {}
function mt.__eq(a, b)
     --Tuples have value semantics for equality in languages like C#, so here's an implementation that does just that. ish, doesn't work for dictionaries, though you could MAKE it work.
    local lenA, lenB = #a, #b
    if lenA ~= lenB then return false end
    for i = 1, math.max(#a, #b) do
        if a[i] ~= b[i] then return false end
    end
    return true
end
function tuple(...)
    return setmetatable({...}, mt)
end
end

function find(list, value)
    for i, _value in ipairs(list) do
        if _value == value then
            return i
        end
    end
    return nil
end

local a = tuple(1, 2, 3)
local b = tuple(1, 2, 3) 
local c = tuple(1, 2)
local d = tuple(1, 2, 4)
local e = tuple(1, 2, 3, 4)

print(a == a) --T
print(a == b) --T --Same values, different object, still equals
print(a == c) --F
print(a == d) --F
print(a == e) --F

local things = {a}

print(find(things, a) ~= nil) --T
print(find(things, tuple(1, 2, 3)) ~= nil) --T
print(find(things, c) ~= nil) --F

I don’t know if table.find is actually implemented like that, it might not work if it uses rawequals instead of ==.

EDIT: This also works:

print(a == {1, 2, 3})
print({1, 2, 3} == a)

but it won’t always work if one of the values has a different __eq metamethod defined, in that case I think it depends on which one comes first.

If you need to use a table as a key, use JSONEncode on it first!

local HttpService = game:GetService("HttpService")
local Key = HttpService:JSONEncode({"d", 12})

local K = {
    [Key] = 6
}

print(K[Key]) 
-- or
-- print(K[HttpService:JSONEncode({"d", 12})]
 

Yes, but not in the way you’re doing it. Just because the table your indexing it with looks the same, doesn’t mean it’s the same.

local thing = {"d",12}
local thing2 = thing
print(thing == {"d",12}) --> false
print(thing == thing) --> true
print(thing == thing2) --> true
print({} == {}) --> false  

thing and thing2 are pointing to the same table, so the two variables are equal. Two tables that look alike aren’t always the same. I suggest using a 2D table like @ThanksRoBama said, or combine the two values in the key.

-- 2D Table:
local Data = {
	d = {[5]=8},
	g = {[2]=1},
}
-- Combined:
local Data = {
	D5 = 6,
	D8 = 8,
	D12 = 2,
}