複製表格 |
|
無法保證一般性的 table.copy
函式適用於所有案例,因為對於特定情況,必須選擇許多不同的面向。例如:共用或複製元表?是否要檢查使用者資料是否有 __copy
元方法?開發人員必須詢問並回答這些問題(以及許多其他問題)。
niektóre 「延伸標準程式庫」例如 Penlight 和 stdlib 為了方便而提供現成的複製函式。在實作自己的函式之前,請檢查它們是否適合你的案例。
以下函式提供一個作為基礎的工作
function table.clone(org) return {table.unpack(org)} end local abc = {5,12,1} local def = table.clone(abc) table.sort(def) print(abc[2], def[2]) -- 12 5
__pairs
元方法的影響。
function shallowcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in pairs(orig) do copy[orig_key] = orig_value end else -- number, string, boolean, etc copy = orig end return copy end
以下是一個簡單的遞迴實作,另外還處理元表並避免 __pairs
元方法。
function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end
透過對程式碼進行一些輕微的編輯,也可以建立一個支援遞迴表格的 deepcopy
函式版本。這樣做的方式是建立一個已複製表格的表格,並將其作為第二個引數提供給 deepcopy
函式。
-- Save copied tables in `copies`, indexed by original table. function deepcopy(orig, copies) copies = copies or {} local orig_type = type(orig) local copy if orig_type == 'table' then if copies[orig] then copy = copies[orig] else copy = {} copies[orig] = copy for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key, copies)] = deepcopy(orig_value, copies) end setmetatable(copy, deepcopy(getmetatable(orig), copies)) end else -- number, string, boolean, etc copy = orig end return copy end
重要的是,只提供一個引數給這個版本的 deepcopy
函式。否則,它會嘗試將第二個引數用作表格,這可能會造成意外的後果。
此外,由於這些函式具有遞迴性,因此使用它們複製非常深的表格可能會溢位堆疊。