SOLVED
moment, I realized that because the iterate function isn’t being run asynchronously I can just add the value to the table, run the iterate function, then remove the added value. (I don’t need to get a new/value table in this case.)I am still curious about strong and weak tables, so if anyone recommends an article about that I’ll mark it as the solution.
Context
I have written a function that iterates over tree structured tables that look like this:
{
A = {
A1 = {};
A2 = {};
};
B = {
B1 = {
B1A = {};
};
B2 = {};
};
}
A visual representation would look like this:
For each item in the tree, an inputted function is run with two parameters: the name of the current node and an array representing the parent nodes.
For example, for item "B1A"
the function would get the tuple ("B1A", {"B1", "B"})
.
Here is the complete code:
local treeIterate
--[[
(tree : Tree, func : function)
Runs func on every memeber of a tree-like table. The inputted function gets two parameters: the current string and an array of previous strings
]]
do
local function cloneAppendToContext(append, context)
local newContext = {append}
for _, contextValue in ipairs(context) do
table.insert(newContext, 2, contextValue)
end
return newContext
end
treeIterate = function(tree, func)
local function iterate(dict, context)
for key, value in pairs(dict) do
func(key, context)
-- (Edit)
--iterate(value, cloneAppendToContext(key, context))
-- SOLUTION:
table.insert(context, 1, key)
iterate(value, context)
table.remove(context, 1)
end
end
iterate(tree, {})
end
end
TreeIterateScript.rbxl (34.6 KB)
Example Usage
Code:
treeIterate({
A = {
A1 = {};
A2 = {};
};
B = {
B1 = {
B1A = {};
};
B2 = {};
};
}, function(key, context)
print("Parent of "..key.." is "..(context[1] or ""))
end)
Output:
Parent of A is
Parent of A1 is A
Parent of A2 is A
Parent of B is
Parent of B2 is B
Parent of B1 is B
Parent of B1A is B1
Questions
My problem is that I want the context table to behave like a value instead of a reference, so that I can append an item to the context and pass it to the iterate function, but then have context remain unchanged for the next iteration of the for loop.
I am curious if there is a better way to do this than my cloneAppendToContext
function, which simply creates a new table and iterates through the old one inserting the values. Maybe there is a way to do this with metatables? Would that be efficient for such a short lasting table?
If cloning the table is the only way, I’m also wondering if something like table.pack(key, table.unpack(context))
is better or if the type conversion is killer for performance.
On a slightly different note, does anyone know if it is bad to declare a function inside of another function? Should I put the func
variable as a parameter and move that outside the scope of the function?
If anyone has some good articles or anything related to this I would really appreciate those.
Thanks a bunch