Get "Parent' Of Table Value?

Given this table:

local a = {
		b = {
			c = "Hello"
		},
		d = {
			e = {
				f = 'World'
			},
			g = true
		}
	}

Assuming it is not allowed for duplicate values to exist, how would I go about accessing the “parent” of e (which is { f = 'World' })

Currently, I’m using this to do it but it seems to not work all the time. Warning: messy/repetitive code

local find
find = function(originalTable, findValue)
	for index, wrappedTable in pairs(originalTable) do
		if wrappedTable == findValue then
			return wrappedTable
		else
			return nil
		end
	end
end

local function getParentOf(tagVal)
		local recursiveLoop
		recursiveLoop = function(parent)
			for k, v in pairs(parent) do
				if type(v) ~= 'table' then continue end
				if find(v, tagVal) then
					return v
				else
					return recursiveLoop(v)
				end
			end
		end
		
		for k, v in pairs(tree) do
			if type(v) ~= 'table' then continue end
			if find(v, tagVal) then
				return v
			else
				return recursiveLoop(v)
			end
		end
	end

Why do you have to access the parent table in such a way?

It’s for traversing through a large table where you don’t necessarily know where the value is that you’re accessing.

What kind of data does this table contain?

The example should be sufficient to represent what it contains.

1 Like

I believe this should work

Given that e has the same reference as in the table. e.g. a.d.e

function lookForParent(parentTable, element)
	for k,v in pairs(parentTable) do
		if v == element then
			return parentTable
		elseif type(v) == "table" then
			local result = lookForParent(v, element)
			if result ~= nil then return result end
		end
	end
	return nil
end

You can’t. The idea of a hierarchy through tables is kinda an illusion, since you’re really just pointing to other tables. There’s no concept of parent/child relationships baked into them. You would have to manually write your own “Parent” key into the table to point back.

While I recommend not doing this, you could go about this as such:

local function AssignParents(tbl, parent)
   for k,v in pairs(tbl) do
      if type(v) == "table" then
         if parent then
            rawset(v, "_parent", parent)
         end
         AssignParents(v, tbl)
      end
   end
end

AssignParents(myTbl)

^ That will cause a stack-overflow if there are any circular references though. But generally, you can see the logic of tracking the parent virtually through each recursion.

6 Likes

Well, this is theoretically possible since the values are unique and you’re just checking the values and returning the parent table that holds it.

I would still recommend sleitnick’s solution

2 Likes