How would i be able to merge tables?

how would i be able to merge these tables together and check if the old (table1) contains some of the same data as the table2 and overwrite the original one with the new one and add more users if a table has other users that the original table doesnt.

example 1

local table1 = {
   ["UserData"] =  ▼  {
      ["MrSherloque"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
    }
}

local table2 = {
   ["UserData"] =  ▼  {
      ["MrSherloque"] =  ▼  {
        ["Stats"] = "Bye World!"
      }
    }
}

local result = {
  ["UserData"] =  ▼  {
    ["MrSherloque"] =  ▼  {
        ["Stats"] = "Bye World!"
    }
  }

}

example 2:

local table1 = {
   ["UserData"] =  ▼  {
      ["MrSherloque"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
    }
}

local table2 = {
   ["UserData"] =  ▼  {
      ["MasterMind"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
    }
}

local result = {
   ["UserData"] =  ▼  {
    ["MrSherloque"] =  ▼  {
        ["Stats"] = "Hello World!"
    }
  };

   ["UserData"] =  ▼  {
      ["MasterMind"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
    }
}

example 3

local table1 = { -- existing data
   ["UserData"] =  ▼  {
      ["MrSherloque"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
     ["MasterMind"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
    }
}

local table2 = {
   ["UserData"] =  ▼  {
      ["MasterMind"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
     ["MrSherloque"] =  ▼  {
        ["Stats"] = "Bye World!"
     }
    }
  
}


local result = {
   ["UserData"] =  ▼  {
    ["MrSherloque"] =  ▼  {
        ["Stats"] = "Bye World!"
    }
  };

   ["UserData"] =  ▼  {
      ["MasterMind"] =  ▼  {
        ["Stats"] = "Hello World!"
      }
    }
}

Now i would like the merging system to be flexible and work for any table. But is that possible?

The results in example 2 and 3 are not valid tables.

You can’t have a ; in the middle of your result table.
You can’t use the same key more than once in a single table (you have "UserData" twice in both results).


Also you should clarify what you want it to do with more than just examples (because then it might not be clear what is changing and why)

You should make a list of requirements/rules for merging.

I would like it to merge tables so the new table overwrites old tables if they have the same tables. and merge new values / tables into the old table if the old table doesnt have that value. also sorry for the bad examples its a little confusing when writing it in the new topic editor

You wouldn’t be able to have two indicies of the same thing, you would have to have the result in the bottom like this

local result = {
   ["UserData"] =  ▼  {
    ["MrSherloque"] =  ▼  {
        ["Stats"] = "Bye World!"
    };
    ["MasterMind"] =  ▼  {
        ["Stats"] = "Hello World!"
    }
  };
}

(unlike what @ketrab2004 says semicolons can be used as commas in tables so it is valid)

the logic you’re trying to implement is semi-advanced as it deals with nested table merging, you will always run into drawbacks from it, nevertheless, you can merge tables like this

function MergeTable(tbl1, tbl2)
   for i,v in pairs(tbl2) do
      tbl1[i] = v
   end
end

this will change the table provided, if you wish to have a completely different unchanged table you can clone tbl1 using table.clone before doing anything to it and then return tbl1

From here it’s adding some extra logic “if typeof(v) == “table” then” and using recursive functions to merge them both if they exist (not going to spoonfeed so you gotta figure that bit out yourself)

2 Likes

I figured out something that works for me thanks!

Was @PostVivic’s post the solution? If so, you should mark it as the solution. Otherwise, what fixed the issue for you?

It wasn’t the final solution i used. Heres what worked for me:

local function MergeTable(tbl1,tbl2)
    local baseTable = table.clone(tbl1) or {}

	local function init(t1,t2)
		for i, v in pairs(t2) do
			if type(v) == "table" then
				if type(t1[i]) ~= "table" then
					t1[i] = {}
				end
				init(t1[i], v)
			else
				if t1[i] == nil then
					t1[i] = v
				end
			end
		end
	end

	init(baseTable,tbl2)

	return baseTable
end
2 Likes

you could just use recursion with one function instead of another as this will not deepclone the table

if I make two tables to merge

local tbl1 = {
   funnyTableIndex = {
      foo = "bar"
   }
}

local tbl2 = {
   funnyTableIndex = {
      foo = "not bar"
   }
}

MergeTable(tbl1, tbl2)

in this situation tbl1.funnyTableIndex.foo will be set to “not bar” because tbl1.funnyTableIndex would not have been cloned. my personal solution to the problem would be this

function MergeTbl(tbl1, tbl2, Path)
   --add *error catching* here so you won't be sent on a "what went wrong"
   --rollercoaster if tbl1 happens to be nil (I think table.clone errors with nil anyway lol)
   local baseTable = table.clone(tbl1)

   for i,v in pairs(tbl2) do
      --typeof instead of type
      --it doesn't make a difference now as you aren't using custom datatypes like vector3s or cframes
      if typeof(v) == "table" then
         if typeof(baseTable[i]) ~= "table" then
            --you can set it to a blank table if you want but imo it opens up the opportunity for soft-errors and that's not good
            error()
         end
         baseTable[i] = MergeTable(baseTable[i], v, if Path then Path.."."..i else i)
      else
         --can remove the if statement, but stuff in tbl2 takes priority over stuff in tbl1
         baseTable[i] = v
      end
   end
   return baseTable
end

this uses recursion to fix that problem, have better error handling, and shows how you can make a path to track down errors

edit: didn’t test it so there might be bugs in it :skull:

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.