有個體會, lua table 的 #操作 是針對 table.insert() / table.remove() 這一對操作的 “操作數維護”:
每次調用 table.insert() 都會是 #操作值增加(這是我自己的表達, 即使 用 #table 取得表的 返回值);
每次調用 table.remove() 都會減少 #操作值。
table 內部元素維護 有兩種方式:
第一種是 使用 table.insert() / table.remove() 這一對
第二種是 使用 operator[]
另外, 采用默認值聲明並定義表, 並且由positive key 時, lua引擎應該會“嘗試”自動調用 table.insert() , 例如
local tb = { 11, 22, c33=33 }
我的假設過程是:
table.insert( tb, 11)
table.insert( tb, 22)
table.insert( tb, 33)
tb[ c33] = 33
有這么個假設 及 上述猜想后, 看如下例子:
local f = io.open( "out.out", "a" ) function trace( tb) f:write( "count of positive lements is ", #tb, "\n" ) for k, v in pairs( tb) do f:write( k, "\t", v, "\n") end end --=============================== create a table local tb = { 11, 22, c33=33 } trace( tb) --=============================== insert positive number elements for i = 1, 10, 1 do table.insert( tb, i) end trace( tb) --================================ add element with operator[] tb[ 88] = 88 trace( tb) --============================== remove elements with nil to operaor[] for i = 1, 3, 1 do tb[ i] = nil end trace( tb) --============================== remove elements with table.remove() for i = 1, 3, 1 do table.remove( tb, 1) end trace( tb) --=============================== add element with operator[] tb[ 98] = 98 trace( tb) f:write( table.maxn( tb) , "\n") f:flush() f:close()
輸入結果將會是 out.out:
count of positive lements is 2 1 11 2 22 c33 33 count of positive lements is 12 1 11 2 22 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 c33 33 count of positive lements is 12 1 11 2 22 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 88 88 c33 33 count of positive lements is 12 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 88 88 c33 33 count of positive lements is 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 88 88 c33 33 count of positive lements is 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 88 88 98 98 c33 33 98
過程分析如下:
local f = io.open( "out.out", "a" ) function trace( tb) f:write( "count of positive lements is ", #tb, "\n" ) for k, v in pairs( tb) do f:write( k, "\t", v, "\n") end end --=============================== create a table local tb = { 11, 22, c33=33 } trace( tb) --[[ 按照上述假設 #操作值 為 2 count of positive lements is 2 1 11 2 22 c33 33 ]] --=============================== insert positive number elements for i = 1, 10, 1 do table.insert( tb, i) end trace( tb) --[[ 這里增加調用了 10次的 table.insert() count of positive lements is 12 1 11 2 22 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 c33 33 ]] --================================ add element with operator[] tb[ 88] = 88 trace( tb) --[[ operator[] 維護表內元素, 並不會修改 #操作值 count of positive lements is 12 1 11 2 22 3 1 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 88 88 c33 33 ]] --============================== remove elements with nil to operaor[] for i = 1, 3, 1 do tb[ i] = nil end trace( tb) --[[ operator[] 維護表元素, 並不會修改 #操作值 count of positive lements is 12 4 2 5 3 6 4 7 5 8 6 9 7 10 8 11 9 12 10 88 88 c33 33 ]] --============================== remove elements with table.remove() for i = 1, 3, 1 do table.remove( tb, 1) end trace( tb) --[[ 3次 table.remove() 操作, 減少 #操作值 count of positive lements is 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 88 88 c33 33 ]] --=============================== add element with operator[] tb[ 98] = 98 trace( tb) --[[ 又一次的 operator[] 操作, 並不會修改 #操作值 count of positive lements is 9 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 88 88 98 98 c33 33 ]] f:write( table.maxn( tb) , "\n") -- 98 f:flush() f:close()
小結:
1.由於 lua table的元素的維護 分為 table.insert() / remove() 與 operator[] 兩套實現機制, 在相對腳本語言, 尤其是項目多人協作、分時段開發時, 很容易產生 2*2 = 4中以上的 table表 元素維護方式, 容易造成混亂, 造成數據不安全問題。 是否應該對那些 涉及需要被 “多處”的 共享table 表 的操作進行 封裝。
2.一個應用, 假如上述成立, 在新增數據時 統一用 table.insert() 帶來簡便, 並獲取“流水號id”:
local tb = {} function InsertTable( container, item ) table.insert( container, item) item.seqno = #container end
不然 直接的 operator[key] = item 得事先確定 key 值; 而在刪除元素時, 不適用 table.remove() 而是用 operator[]:
--未考慮 nil 的key 判斷 function RemoveByKey( container, key ) container[ key] = nil end function RemoveByItem( container, item ) container[ item.seqno] = nil end
這樣可保證在 container 的 #操作值 只遞增, 是一個 “流水號”。