Is it possible to get a key name in a table?

My apologies if this has been already asked and this questions sounds a bit dumb, but is it possible to get a key name in a table?

For an example:

local t = {apple = 10, orange = 5};
print(t[1]) --> 10

How can I get the string “apple” instead of 10 with this table format? Or it’s impossible?

6 Likes

Try using table.find function from the table library. I’m not entirely sure if it actually works on dictionary.

table.find is for arrays, in fact everything in the table library is meant for arrays.

@Headstackk Your question is confusing and contradictory, you want to find “apple” from 10 yet you can see that “apple” already exists as an index?

I think you mean something like just checking if there is an existing index for value 10?

If the above is true, just use pairs lookup
-- example function code
for index, value in pairs(t) do
    if value == 10 then
       return index
    end
end

You can’t go from value to index though like you would index to value.

4 Likes

Well, actually no. I want to find Apple without knowing 10

2 Likes

you can lookup keys like so: t["apple"] --> 10

t[1] will be nil as you’re using strings instead of numeric indices, which makes it a dictionary, rather than an array.

1 Like

Alternative:

local t = {
    { key = "apple", value = 10 },
    { key = "orange", value = 5 }
}

print(t[1].key) -- apple
11 Likes

If you want to have it like, you give the function a key (eg: Apple) and you want the value (eg: 10) you could make your function simply like this:

local t = {apple = 10, orange = 5}

local function getValue(key)
   for i, v in pairs(t) do
    if i == key then
       return v
    end
   end
end

print(getValue("apple")) <-- Should print 10

It seems like you are trying to get the value from a table but OP asked how to get the key from a table.

1 Like
local t = {apple = 10, orange = 5}

local function getValue(key)
	local i = 1 
	for k, v in pairs(t) do
		i = i + 1
		if i == key then
			return {
				key = k,
				value = v
      			}
		end
	end
end

print(getValue(1)) --> returns a table with the key and value

Won’t be in the same order all the time, but basically works the same way. It’s impossible to have a dictionary ordered the same without some array to show the original order of the dictionary.

Regardless of the fact that you can only access indexes a certain way depending on the way you define them, it (to an extent but not exactly) would be possible if you could traverse dictionaries according to apparent visual order, which you cannot.

You can however change that to an array (containing dictionaries) :

local t = {{apple = 10}, {orange = 5}};

local t2 = t -- let __index fire for every index
t = setmetatable({}, {__index = function(self, k)
		local v = t2[k] -- prevent C stack overflow
		local ind = next(v)
		return v[ind]
	end}
) 
-- the way this is set up, it returns just the value like your requirement...
-- but you'll be forced to define only one ind+val pair in each entry ({})
print(t[1]) --> 10
print(t[2]) --> 5
1 Like

finding a value given a key:

local t = { apple = 10, orange = 5 }

t["apple"] --> 10

finding a key given a value

local function FindKey(tab, val)
    for key, value in next, tab do
        if (value == val) then
            return key
        end
    end
end

FindKey(t, 10) --> "apple"

mixing arrays and dictionaries

local t = {
    apple = 10,
    orange = 5,

    [1] = "apple",
    [2] = "orange"
}

t[1] --> "apple"
t[t[1]] --> 10
t["apple"] --> 10

or you can implement custom Enums

4 Likes

I’ll add on to this method, you can also have a reverse lookup table. You can set it up like this,

local t = {apple = 10, orange = 5}
local reverseTable = {}
for key, value in pairs(t) do
    reverseTable[value] = key
end

print(reverseTable[10]) --> apple

You are doubling memory this way but it has its uses. A lot of good ideas in this thread for how to go about it.

2 Likes

My guess is you’re making some kind of inventory system? To get the name I would just do

local t = {
    ["Apple"] = {
        ["Name"] = "Apple"
        ["Amount"] = 10
    },
     ["Orange"] = {
        ["Name"] = "Orange"
        ["Amount"] = 5
    }
}

Or just use an ipairs loop and get the key from the value if it’s a different problem.

Hey, you forgot to do rawget for this:

rawget(v, index)

I didn’t forget to do it I didn’t mean to there’s no use for it.

There’s no need to use rawget there when you know v[ind] won’t trigger any written code bound to __index anyway, also owing to the nature of this solution you’re restricted to having to index in a way that won’t cause issues for the system’s design.
I only used rawget in the beginning so we don’t end up with an infinite __index.

Yeah you’re right, you were making a table proxy, you probably shouldn’t have used rawget at all since you were using a table proxy.

This time you’re right I probably forgot what I was doing, failed to notice it at the time of responding before because I made the mistake of bothering to reply without understanding my code.

But then again what’s the point in bumping a topic just to point out an unnecessary line of code? DM’ing me would’ve resulted in the same outcome.

Yeah you’re right, sorry about that.

local function GetKeyName(Table, Index)
	if typeof(Table) == "table" and typeof(Index) == "number" then
		local TableIndex = 0
		for Key, Value in pairs(Table) do
			TableIndex = TableIndex + 1
			if TableIndex == Index then
				return Key
			end
		end
	end
end

Usage: GetKeyName(t, 1) will return “apple”.

2 Likes