Today, I give you two simple but helpful resources from my library: AreTablesSame - Does a seep search to check if two tables are equal DeepCopy - Creates a copy of a given table and all of its sub-tables
Simply checking if two tables are equal using the == operator does not work. Comparing tables does not compare the contents of the tables, only the memory addresses. Thus, we have AreTablesSame for this case. For example, we don’t need to make a data store set request if our save data matches the data we had upon joining the game. We would need a special utility to check the two tables.
function KeysMatch(table1, table2, key)
if table2[key] == nil then
return
end
if typeof(table1[key]) ~= typeof(table2[key]) then
return
end
if typeof(table1[key]) == "table" then
if not CheckKeys(table1[key], table2[key]) then
return
end
elseif table1[key] ~= table2[key] then
return
end
return true
end
function CheckKeys(table1, table2)
if not table1 then
return
end
for key in pairs(table1) do
if not KeysMatch(table1, table2, key) then
return
end
end
return true
end
function AreTablesSame(table1, table2)
if not CheckKeys(table1, table2) then
return
end
if not CheckKeys(table2, table1) then
return
end
return true
end
return AreTablesSame
For copying tables, we can usually rely on table.clone. However, if we have embedded tables, they will not be copied using this method. We need a utility to recursively copy the table’s contents. Therefore, we do it manually.
function Copy(original, copy)
for key, value in pairs(original) do
if typeof(value) == "table" then
copy[key] = {}
Copy(original[key], copy[key])
else
copy[key] = value
end
end
end
return function(original)
local copy = {}
Copy(original, copy)
return copy
end
Hope that helps anybody looking for a quick solution to these problems.
--[[ READ ME:
Use of this library requires that dictionaries you pass into it do not have two of the same keys. No two keys can be the same.
]]
local DictionaryUtils = {}
-- Deeply copies a dictionary.
function DictionaryUtils.DeepCopy(dictionaryToCopy)
if type(dictionaryToCopy) ~= "table" then return dictionaryToCopy end
local deepCopiedTable = {}
for index, value in pairs(dictionaryToCopy) do
if type(value) == "table" then
value = DictionaryUtils.DeepCopy(value)
end
deepCopiedTable[index] = value
end
return deepCopiedTable
end
function DictionaryUtils.DeepPrint(dictionaryToCopy)
if type(dictionaryToCopy) ~= "table" then return dictionaryToCopy end
local deepCopiedTable = {}
for index, value in pairs(dictionaryToCopy) do
print(tostring(index), tostring(value))
if type(value) == "table" then
value = DictionaryUtils.DeepCopy(value)
end
deepCopiedTable[index] = value
end
return deepCopiedTable
end
-- Copies a dictionary.
function DictionaryUtils.ShallowCopy(dictionaryToCopy)
if type(dictionaryToCopy) ~= "table" then return dictionaryToCopy end
local shallowCopiedTable = {}
for index, value in pairs(dictionaryToCopy) do
shallowCopiedTable[index] = value
end
return shallowCopiedTable
end
-- Checks a dictionary to see if a specific key is in the dictionary
function DictionaryUtils.IsKeyInDictionary(Dictionary, Key)
for index, value in pairs(Dictionary) do
if index == Key then
return true
end
if type(value) == "table" then
local result = DictionaryUtils.IsKeyInDictionary(value, Key)
if result then return true end
end
end
end
-- Sets a pre-existing key in a dictionary to a new value deeply.
function DictionaryUtils.DeepSet(dictionaryToSet, keyToSet, valueToSet)
if type(dictionaryToSet) ~= "table" then return dictionaryToSet end
if not DictionaryUtils.IsKeyInDictionary(dictionaryToSet, keyToSet) then
local dictionaryToSet = DictionaryUtils.DeepCopy(dictionaryToSet)
dictionaryToSet[keyToSet] = valueToSet
return dictionaryToSet
end
local deepCopiedTable = {}
local foundKey = false
for index, value in pairs(dictionaryToSet) do
if type(value) == "table" then
value = DictionaryUtils.DeepSet(value, keyToSet, valueToSet)
end
if index == keyToSet then
deepCopiedTable[keyToSet] = valueToSet -- Overwrites the same key with a new value.
foundKey = true
else
deepCopiedTable[index] = value
end
end
return deepCopiedTable
end
-- Gets the value of a key.
function DictionaryUtils.DeepGetValueOfKey(dictionary, keyToGet)
for index, value in pairs(dictionary) do
if index == keyToGet then
return value
end
if type(value) == "table" then
local result = DictionaryUtils.DeepGetValueOfKey(value, keyToGet)
if result then
return result
end
end
end
end
-- Takes a function with the parameters (index, value) and runs it deeply on every key value pair.
function DictionaryUtils.DeepFunction(dictionary, functionToRun, cleaning : boolean)
for index, value in pairs(dictionary) do
if type(value) == "table" then
DictionaryUtils.DeepFunction(value, functionToRun)
end
functionToRun(index, value)
end
end
-- Checks a dictionary to see if a key-value pair is existant in the dictionary.
function DictionaryUtils.IsPairInDictionary(dictionary, keyToCheck, valueOfKey)
for index, value in pairs(dictionary) do
if index == keyToCheck and value == valueOfKey then
return true
end
if type(value) == "table" then
local result = DictionaryUtils.IsPairInDictionary(value, keyToCheck, valueOfKey)
if result then return true end
end
end
return false
end
-- Compares two dictionary deeply to see if they are the same.
function DictionaryUtils.CheckIfSame(d1, d2)
if type(d1) ~= "table" or type(d2) ~= "table" then return false end
for index, value in pairs(d1) do
if not DictionaryUtils.IsPairInDictionary(d2, index, value) then return false end
end
for index, value in pairs(d2) do
if not DictionaryUtils.IsPairInDictionary(d1, index, value) then return false end
end
return true
end
-- Returns the amount of key-value pairs in a dictionary.
function DictionaryUtils.ShallowDicToNum(dictionary : any)
local counter = 0
for index, value in pairs(dictionary) do
counter+=1
end
return counter
end
return DictionaryUtils