標籤:style blog http color io 使用 ar strong for
lua,一款很輕量級很nice很強大的指令碼語言,做為lua中使用最為頻繁的table表,在使用之時還是有頗多的好處與坑的;
下面是大牛 雲風的一片關於lua table的blog,可使得對lua table內在機制 窺測一二;
lua 的整體效率是很高的,其中,它的 table 實現的很巧妙為這個效率貢獻很大。
lua 的 table 充當了數組和映射表的雙重功能,所以在實現時就考慮了這些,讓 table 在做數組使用時盡量少效率懲罰。
lua 是這樣做的。它把一個 table 分成數組段和 hash 段兩個部分。數字 key 一般放在數組段中,沒有初始化過的 key 值全部設定為 nil 。當數字 key 過於離散的時候,部分較大的數字 key 會被移到 hash段中去。這個分割線是以數組段的利用率不低於 50% 為準。 0 和 負數做 key 時是肯定放在 hash 段中的。
string 和 number 都放在一起做 hash ,分別有各自的演算法,但是 hash 的結果都在一個數值段中。hash 段採用閉散列方法,即,所有的值都存在於表中。如果hash 發生碰撞,額外的資料記在空閑槽位裡,而不額外分配空間存放。當整個個表放滿後,hash 段會擴大,所有段內的資料將被重新 hash ,重新 hash 後,衝突將大大減少。
這種 table 的實現策略,首先保證的是尋找效率。對於把 table 當數組使用時將和 C 數組一樣高效。對於 hash 段的值,尋找幾乎就是計算 hash 值的過程(其中string 的 hash 值是事先計算好儲存的),只有在碰撞的時候才會有少許的額外尋找時間,而空間也不至於過於浪費。在 hash 表比較滿時,插入較容易發生碰撞,這個時候,則需要在表中找到空的插槽。lua 在table 的結構中記錄了一個指標順次從一頭向另一頭循序插入來解決空槽的檢索。每個槽點在記錄 next 指標儲存被碰撞的 key 的關聯性。
整個來說,這種解決方案是非常不錯的。
關於映射表的實現,我前段時間也做過一個別的研究。貼在留言本上:
<a href="http://www.codingnow.com/2004/board/view.php?paster=777&reply=0">樹表結合的一種映射表實現</a>
<a href="http://www.codingnow.com/2004/board/view.php?paster=776&reply=0">在 vector , map , list 間取得平衡</a>
原文連結: http://blog.codingnow.com/2005/10/lua_table.html
即便作為lua 開發蠻久的coder來講,很多東西不親自去考究一下,還不是很清晰的,不如lua table的長度問題就是一個 很奇葩的例子;下面的這些也許你就不是很清楚了;
想要取得lua table長度,有這麼幾種方法,table.getn(table_name), #table_name, table.maxn(table_name), 再加上 ipairs(table_name) 和pairs(table_name)遍曆;
根據云風所寫的文章可以得知,lua的兩種不同的儲存方式,自然的,上述的幾種 取得lua table 長度的幾種方式也 存在區別;
table.maxn(table)
table.maxn()函數返回指定table中所有正數key值中最大的key值. 如果不存在key值為正數的元素, 則返回0. 此函數不限於table的數組部分.
table.getn(table)
返回table中元素的個數
#(table)
返回的是lua table 中key為連續整型數字(抑或是 預設整型)的長度數;
pairs()函數基本和ipairs()函數用法相同, 區別在於pairs()可以遍曆整個table, 即包括數組及非數組部分.
關於對lua table長度的問題,http://blog.csdn.net/dssdss123/article/details/12676329 對於一些奇葩問題的講述還是有些深入的;親測【lua version=5.1.4】,的確如此;
但是還是有些東西需要補充的,對於 #用法,其表現和table.getn()在很多極端的情況下都是類似的;table.maxn(),因為擷取的是table中所有正數key值中最大的key值.可以不連續;
local tblTest ={ "this 1", "this 2", [3] = 2, [4] = 5, [5] = 7, "this 3", [10] = 10,}print(table.getn(tblTest))print(#(tblTest))print(table.maxn(tblTest))--===========================>lua -e "io.stdout:setvbuf ‘no‘" "filedeal.lua" 5510--===========================local tblTest ={ "this 1", [3] = 2, [4] = 5, [5] = 7, "this 3", --"adsfasd", [10] = 10,}print(table.getn(tblTest))print(#(tblTest))print(table.maxn(tblTest))--===========================>lua -e "io.stdout:setvbuf ‘no‘" "filedeal.lua" 5510--===========================local tblTest ={ "this 1", [3] = 2, [4] = 5, [5] = 7, --"adsfasd", [10] = 10,}print(table.getn(tblTest))print(#(tblTest))print(table.maxn(tblTest))--===========================>lua -e "io.stdout:setvbuf ‘no‘" "filedeal.lua" 1110--===========================
上述三個tabTest 的不同在於 這都是lua預設的下表是從1開始,有兩個的預設的,使得 [3]=2,這項元素足以將連續性接上,當接不上的時候,因為不連續行,自然列印值有所不同了;
倘若在後面或者該表 其中再墜入一個nil,所輸出來的內容又是不一樣的:所以~不要在lua的table中使用nil值,如果一個元素要刪除,直接remove,不要用nil去代替。
倘若再將元素後面加一項 下表預設的元素,其結果會怎樣呢? 例 如下代碼:
local tblTest ={ "this 1", [3] = 2, [4] = 5, [5] = 7, "this 3", --"adsfasd", [10] = 10,}for k , v in ipairs(tblTest) do print(k,v)end--=============================1 this 12 this 33 24 55 7--=============================local tblTest ={ "this 1", [3] = 2, [4] = 5, [5] = 7, "this 3", "this 4", --"adsfasd", [10] = 10,}for k , v in ipairs(tblTest) do print(k,v)end--=============================1 this 12 this 33 this 44 55 7--=============================
由此可見,lua 預設的下表值會將顯示的覆蓋,即便是 再調整下順序 也是如是,至於為何如此,不理解,有待參悟【歡求 大神指正】;
這樣的意外在lua中 挺多的,只要明白了 基本的原理,倒也不足為奇了;
至於lua table的遍曆 可參見 http://rangercyh.blog.51cto.com/1444712/1032925 這這篇文章;講的挺詳細的;
另外: 關於lua table的其他小問題:
1, 配置lua table 元素之間,以”,“ 或者”;“完全是一樣的【可參見lua手冊】,看你的愛好了,推薦的是:用分好可以作為 元素類型的不同而分割開顯示下;
2,不要在lua的table中使用nil值,如果一個元素要刪除,直接remove,不要用nil去代替。
3,判斷lua table 是否為nil 不能用 if a == {} then 【錯誤的】(這樣的結果就是a == {}永遠返回false,是一個邏輯錯誤。因為這裡比較的是table a和一個匿名table的記憶體位址。);
if table.maxn(a) == 0 then 【錯誤的】這樣做不保險啊,除非table的key都是數字,而沒有hash部分。
if #(a) == 0 then 也是不靠譜的,除非你能保證沒人這樣寫這個table like this:tab = {nil,1,nil;} 用#tab print出來 的確是0, 能說此tab是nil的?
可以使用lua內建的next來判斷; if next(a) == 0 then ;
4,平時學習工作中遇到挺多的,一旦想要寫出來時,有些總想不起來了,待之後想到了再添加好了【未完待續...】
lua的table表處理 及注意事項