Table duplicating?

So I’m currently have a table called SlotsChanged which is a table containing a table for each slot changed.
The table inside is in the following form: {SlotNumber, SlotItemID, SlotQuantity}
However, when trying to achieve is, the main table changes from some reason.

--[[
CatagoryData = {
    [1] = {1, 1};
    [2] = {2, 1};
    [3] = {3, 1};
    [4] = {4, 1};
    [5] = {1221, 1};
}
SlotsChanged = {}
]]

CatagoryData[#CatagoryData+1] = {ItemID, Amount};   

table.insert(SlotsChanged, CatagoryData[#CatagoryData])          -- Inserts the table that contains the last slot data
table.insert(SlotsChanged[#SlotsChanged], 1, #CatagoryData)      -- Inserts the position of the slot in the CatagoryData just inserted, i.e. 5, into the first position of the table containing that slot data

print(unpack(CatagoryData[#CatagoryData]))

This prints 5 1221 1
So there is an extra value at the start of the table, which is supposed to be added only to the table inside of SlotsChanged.

4 Likes

Alright, here’s what I’ve got so far,

--[[
SlotsChanged = {
    [1] = {1, 1};
    [2] = {2, 1};
    [3] = {3, 1};
    [4] = {4, 1};
    [5] = {1221, 1};
}
]]

Amount = math.min(Catagory[2], Remainder);          -- 1
CatagoryData[#CatagoryData+1] = {ItemID, Amount};   

table.insert(SlotsChanged, CatagoryData[#CatagoryData])          -- Inserts the table at the end of CategoryData into the SlotsChanged table
table.insert(SlotsChanged[#SlotsChanged], 1, #CatagoryData)      -- Inserts the length of CategoryData, i.e. 5 into position 1 of the table at the end of SlotsChanged table

print(unpack(CatagoryData[#CatagoryData]))
Remainder = Remainder - Amount;

Maybe having what it’s probably doing explained back to you might help, I’m still having trouble understanding your problem, sorry.

2 Likes

Tables are passed by reference and not value, so you have to copy them manually. An easy way of shallow copying an array is x = {unpack(t)}.

If you want deeper copying or dictionaries you’d need to write a recursive function to do it.

12 Likes

The CatagoryData is a simply array, where CatagoryData[1] is a table containing the data of slot 1.
Would you method work with that?

@Autterfly mentioned a really interesting topic which pass by reference datatypes and pass by value datatypes. (Also knwon as reference and primitive datatypes)

Here is an example that will make it clear for you:
Let’s say we have table t1, which has a bunch of random stuff in it, then what we wanna do is make a second table t2 which will have the same stuff as t1, or in other words it’s a copy of t1.

local t1 = {"hi", 42, workspace}
local t2 = t1 --t2 is a copy of t1

And let’s say we changed one of the values stored in t2

local t1 = {"hi", 42, workspace}
local t2 = t1 

t2[1] = "bye"

Now here is the question, will “hi” change to “bye” just in t2 and t1 wouldn’t be affected, or will it change it for both t2 and t1?

The answer is, it will change it to both, because tables are pass by reference! Which means, when we assign t2 to t1 we are not making another separate table that has the same stuff as t1, we are basically storing a reference to t1, so basically t2 just refers to t1 and doesn’t create another table that’s a replica.
And in the memory of the computer, t2 stores the address to t1.

print(t1[1]) --bye
print(t2[1]) --bye

And in most programming languages, all datatypes are pass by value (stuff like strings booleans numbers…)
and stuff like tables and functions are pass by reference

3 Likes

Wouldn’t it just be easier to use JSONEncode and Decode for depper copying?

4 Likes

It has a delay for the calculation or both decoding and encoding.

Seems interesting :thinking:
But would the unpack method work for arrays only? Or would it work with dictionaries too?
Lets say I want to remove an item from the inventory but not sure if there is enough amount.
I would need to remove it from a clone, see if there was any quantity not removed, and if it was all removed then it will set the default table to that table, how would I achieve this?

That would work if your table consisted of bool, number, string and table values. Otherwise, functions, coroutines and userdata values cannot be serialized (or is tricky to do so).

1 Like

Forgot to mention, the data needed to be cloned is only a table made of arrays, where the index is the slot number.

For deeper copying, you might want to copy stuff like metatables copied or have recursive tables. As far as I know, JSONEncode can’t handle either properly.

@AlvinPolys Using unpack only works for arrays.

1 Like

Would I need to re pack it or just Cloned = {unpack(TableHere)}?

My apologies if I caused any confusion with my previous post.

What I was suggesting was using JSONEncode and JSONDecode for a deep copy/clone of an existing tables whose values are only string, number, booleans and other tables. In for example JavaScript, this method is considered one of the fastest for values like these, hence why there aren’t any (completely) native implementations for it (you have Object.assign but not for deeper values).


I doubt Lua would be significantly slower than JavaScript’s implementation, but I’ll make sure to test it before giving a final answer. I haven’t tried it out before :slight_smile:

Unless Roblox has a non-standard way of encoding a table into a valid JSON (which I doubt), you’re correct, it’s not possible to have JSONEncode include metatables.

This is just me picking on you but I would just call it for “referring it to t1” instead. You explained it later in your post :stuck_out_tongue:

3 Likes

I think it’s important to note that you can restructure recursive functions in a non-recursive way by queueing data in a while loop. The while loop simply processes one queue item (a table) at a time until the entire table is copied.

A simple way for arrays (as noted by @Autterfly) is to unpack the table and construct a new table with it. This splits the entire table into a list of arguments which can be used to construct a table.

For dictionaries and complex data types you will need to use for loops though.