This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
diegodan1893's profile picture

How to copy a table

Started by diegodan1893, 11 January 2013 - 06:05 AM
diegodan1893 #1
Posted 11 January 2013 - 07:05 AM
Many people don't know that in LUA you can't copy a table with simply do copy = table because if you modify the original table the copy will also be affected.

Why that doesn't work?
In lua-users wiki the say that a generic table.copy function is not guaranteed to suite all use-cases, as there are many different aspects which must be selected for the specific situation. For example: should metatables be shared or copied? Should we check userdata for a __copy metamethod? These questions (as well as many others) must be asked and answered by the developer.

So how to copy a table?
A simple function to make a copy of a table is really easy to implement. Just make a function like this.


function copyTable(t)
local t2 = {} –We define here the new table

for k, v in pairs(t) do –Don't use ipairs here because that only works with numeric inexes
t2[k] = v –Here we copy the key and the value from the original table
end

return t2 –Return the copyed table
end

–To copy the function you only have to do:
copy = copyTable(tableToCopy)

What happens with metatables?
I don't know how to use metatables, so I can't help here.

Why did you use quote instead of code for the function?
Because code in this forum doesn't highlight LUA sintax and I have a plugin to copy the code with sintax highlight from Notepad++, so I think it's better to understand the funtion than plain text with some colors that doesn't say anything.

I hope this can help you. If you have any questions, post a comment.

EDIT:
Here is a easier way and it works better (to copy a table inside of a table) but it's only compatible with ComputerCraft:

function copyTable(t)
   local aux = textutils.serialize(t)
   local t2 = textutils.unserialize(aux)
   return t2
end
anonimo182 #2
Posted 11 January 2013 - 07:08 AM
1. Good tutorail of copying tables

2. Code tags does hightlight
diegodan1893 #3
Posted 11 January 2013 - 07:12 AM
1. Good tutorail of copying tables
Thanks :D/>

2. Code tags does hightlight
But not LUA syntax
Orwell #4
Posted 11 January 2013 - 10:25 AM
Your example function does what is called a shallow copy, instead of a deep copy. This means that when the table contains tables as values, they will still be references to the tables in the original table.
You'd have to use a recursive function to fix this.

Edit: I adapted yours quickly; can't test it right now, but I'm quite sure it works.
function copyTable(t)
if type(t) ~= "table" then
return t
end

local t2 = {} –We define here the new table

for k, v in pairs(t) do –Don't use ipairs here because that only works with numeric inexes
t2[k] = copyTable(v) –Here we copy the key and the value from the original table
end

return t2 –Return the copied table
end

Cyclic recursion would screw it up though, but I haven't seen people using that often. :P/>
immibis #5
Posted 11 January 2013 - 12:36 PM
You forgot to copy the keys and don't handle cycles. Untested code:

local function copyTableInternal(source, seen)
  if type(source) ~= "table" then return source end
  if seen[source] then return seen[source] end

  local rv = {}
  seen[source] = rv
  for k,v in pairs(source) do
    rv[copyTableInternal(k, seen)] = copyTableInternal(v, seen)
  end
  return rv
end
function copyTable(source)
  return copyTableInternal(source, {})
end
Orwell #6
Posted 11 January 2013 - 12:53 PM
You forgot to copy the keys and don't handle cycles. Untested code:

local function copyTableInternal(source, seen)
  if type(source) ~= "table" then return source end
  if seen[source] then return seen[source] end

  local rv = {}
  seen[source] = rv
  for k,v in pairs(source) do
	rv[copyTableInternal(k, seen)] = copyTableInternal(v, seen)
  end
  return rv
end
function copyTable(source)
  return copyTableInternal(source, {})
end
Yeh, you're right. :)/> I guess I was too busy making a point <_</>. Clever way of doing it btw. :)/>
diegodan1893 #7
Posted 16 January 2013 - 06:26 AM
Maybe the easiest way is:

function copyTable(t)
   aux = textutils.serialize(t)
   t2 = textutils.unserialize(aux)
   return t2
end
PixelToast #8
Posted 16 January 2013 - 08:28 AM
you forgot to localize ;)/>
diegodan1893 #9
Posted 16 January 2013 - 09:30 AM
you forgot to localize ;)/>

localize?
Orwell #10
Posted 16 January 2013 - 09:40 AM
you forgot to localize ;)/>

localize?
Declaring your variables as local. Which could be a big deal in some cases and is good coding practice. But as it's not in the scope if this tutorial, I don't think it's that big of a deal.
theoriginalbit #11
Posted 17 January 2013 - 10:55 PM
damn wish i saw this earlier, could have pointed the ask a pro thread here instead of explaining it myself…
diegodan1893 #12
Posted 18 January 2013 - 07:58 AM
you forgot to localize ;)/>

localize?
Declaring your variables as local. Which could be a big deal in some cases and is good coding practice. But as it's not in the scope if this tutorial, I don't think it's that big of a deal.

Yes, I forget it because I wrote this without testing or anything.