I only made this because of a post I came across a post of someone trying to send a table that has a cyclic reference over a bindable function. Attempting this will throw an error. So I made a simple module to remove cyclic references in tables. I don’t know if this problem is common, I don’t know if anyone cares, but I made the module so I thought I may as well post it here.
While this may not be the most efficient method, it does work on all types of tables, arrays, dictionaries and mixed tables. I have tested it with a depth of 4 with no issues but I cannot say if it’ll work at every depth.
The usage is simple:
local removeCyclic = require((...).RemoveCyclic).removeCyclic
local t1 = removeCyclic(t)
When using this module, the original table is slightly altered, but still has cyclic references which makes it unusable. If you’re wondering why I don’t deep copy it, well it’s pretty obvious, the cyclic references would cause a deep copy to infinitely run. For this reason I recommend clearing the original table from memory after using this utility.
As stated, this works on all types of tables including mixed tables, arrays within dictionaries and dictionaries within arrays.
Here’s the module:
And if you’re into the nerdy technical stuff, here’s the source:
Nerdy technical stuff
local module = {}
function removeCyclic(t, p)
local t1 = {}
for k in pairs(t) do
if table.find(p, t[k]) then
continue
end
if typeof(t[k]) ~= "table" then
t1[k] = t[k]
else
table.insert(p, t[k])
t1[k] = t[k]
local nonCyc = removeCyclic(t[k], p)
for k1 in pairs(t1[k]) do
if not nonCyc[k1] then
t1[k][k1] = nil
end
end
if getTableType(t1[k]) == "Array" then
removeNilFromTable(t1[k])
end
end
end
return t1
end
function removeNilFromTable(t)
local prev = 0
for i, v in pairs(t) do
if typeof(v) == "table" and getTableType(v) == "Array" then
removeNilFromTable(v)
end
if prev+1 ~= i then
table.remove(t, prev+1)
end
prev = i
end
end
--[[
Source: https://devforum.roblox.com/t/detecting-type-of-table-empty-array-dictionary-mixedtable/292323/15
@XAXA
]]
function getTableType(t)
if next(t) == nil then return "Empty" end
local isArray = true
local isDictionary = true
for k, _ in next, t do
if typeof(k) == "number" and k%1 == 0 and k > 0 then
isDictionary = false
else
isArray = false
end
end
if isArray then
return "Array"
elseif isDictionary then
return "Dictionary"
else
return "Mixed"
end
end
function module.removeCyclic(t)
local nonCyclic = removeCyclic(t, {t})
if getTableType(nonCyclic) == "Array" then
removeNilFromTable(nonCyclic)
end
return nonCyclic
end
return module
As I said, maybe not the best, or the fastest, but a method that works on all types of tables.