lua 的 table表 大小、元素個數 #操作 的體會【結論是錯誤的, 此后再更新】


有個體會, 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 的 #操作值 只遞增, 是一個 “流水號”。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM