鍍金池/ 教程/ Java/ table 庫
定時任務
函數(shù)的參數(shù)
超時
一個 openresty 內存“泄漏”問題
獲取 uri 參數(shù)
局部變量
sleep
灰度發(fā)布
TIME_WAIT
代碼覆蓋率
連接池
CentOS 平臺安裝
稀疏數(shù)組
如何只啟動一個 timer 工作?
變量的共享范圍
break,return 關鍵字
Nginx
SQL 注入
如何引用第三方 resty 庫
不同階段共享變量
獲取請求 body
動態(tài)生成的 lua-resty-redis 模塊方法
動態(tài)加載證書和 OCSP stapling
repeat 控制結構
編碼為 array 還是 object
Nginx 靜態(tài)文件服務
執(zhí)行階段概念
Lua 函數(shù)
日期時間函數(shù)
健康監(jiān)測
與其他 location 配合
for 控制結構
函數(shù)定義
HTTPS 時代
點號與冒號操作符的區(qū)別
String 庫
文件操作
OpenResty 最佳實踐
<code>ngx.shared.DICT</code> 非隊列性質
使用動態(tài) DNS 來完成 HTTP 請求
代碼規(guī)范
什么是 JIT?
Windows 平臺安裝
正確的記錄日志
LuaNginxModule
不用標準庫
C10K 編程
控制結構
請求中斷后的處理
Lua 環(huán)境搭建
Test::Nginx 能指定現(xiàn)成的 nginx.conf,而不是自動生成一個嗎
Lua 基礎數(shù)據(jù)類型
動態(tài)限速
PostgresNginxModule
簡單API Server框架
API 測試
location 匹配規(guī)則
虛變量
單元測試
防止 SQL 注入
select + set_keepalive 組合操作引起的數(shù)據(jù)讀寫錯誤
阻塞操作
全動態(tài)函數(shù)調用
Web 服務
典型應用場景
Nginx 新手起步
TLS session resumption
輸出響應體
調用代碼前先定義函數(shù)
module 是邪惡的
怎樣理解 cosocket
模塊
Socket 編程發(fā)展
如何對 Nginx Lua module 添加新 api
如何在后臺開啟輕量級線程完成定時任務?
如何定位問題
table 庫
json 解析的異常捕獲
如何安裝火焰圖生成工具
lua 中如何 continue
if 是邪惡的
為什么我們的域名不能被解析
抵制使用 module() 定義模塊
測試
body 在 location 中的傳遞
Lua 入門
子查詢
pipeline 壓縮請求數(shù)量
如何發(fā)起新 HTTP 請求
Lua 簡介
緩存失效風暴
Ubuntu 平臺安裝
日志輸出
緩存
Lua 面向對象編程
Nginx 陷阱和常見錯誤
Redis 接口的二次封裝(發(fā)布訂閱)
日志
訪問有授權驗證的 Redis
正則表達式
lock
熱裝載代碼
調用 FFI 出現(xiàn) &quot;table overflow&quot;
數(shù)據(jù)合法性檢測
禁止某些終端訪問
控制結構 if-else
調試
與 Docker 使用的網絡瓶頸
PostgresNginxModule 模塊的調用方式
用 do-end 整理你的代碼
FFI
什么時候使用
簡介
環(huán)境搭建
Mac OS X 平臺安裝
火焰圖
負載均衡
while 型控制結構
如何定位 openresty 崩潰 bug
使用 Nginx 內置綁定變量
判斷數(shù)組大小
請求返回后繼續(xù)執(zhí)行
Redis 接口的二次封裝
KeepAlive
反向代理
協(xié)議無痛升級
數(shù)學庫
元表
Vanilla 介紹
HelloWorld
LuaCjsonLibrary
持續(xù)集成
代碼靜態(tài)分析
網上有大量對 Lua 調優(yōu)的推薦,我們應該如何看待?
script 壓縮復雜請求
非空判斷
性能測試
函數(shù)返回值
API 的設計
kong 介紹
表達式
不支持事務
LuaRestyDNSLibrary 簡介

table 庫

table 庫是由一些輔助函數(shù)構成的,這些函數(shù)將 table 作為數(shù)組來操作。

下標從 1 開始

Lua 中,數(shù)組下標從 1 開始計數(shù)。

官方解釋:Lua lists have a base index of 1 because it was thought to be most friendly for non-programmers, as it makes indices correspond to ordinal element positions.

確實,對于我們數(shù)數(shù)來說,總是從 1 開始數(shù)的,而從 0 開始對于描述偏移量這樣的東西有利。而 Lua 最初設計是一種類似 XML 的數(shù)據(jù)描述語言,所以索引(index)反應的是數(shù)據(jù)在里面的位置,而不是偏移量。

在初始化一個數(shù)組的時候,若不顯式地用鍵值對方式賦值,則會默認用數(shù)字作為下標,從 1 開始。由于在 Lua 內部實際采用哈希表和數(shù)組分別保存鍵值對、普通值,所以不推薦混合使用這兩種賦值方式。

local color={first="red", "blue", third="green", "yellow"}
print(color["first"])                 --> output: red
print(color[1])                       --> output: blue
print(color["third"])                 --> output: green
print(color[2])                       --> output: yellow
print(color[3])                       --> output: nil

從其他語言過來的開發(fā)者會覺得比較坑的一點是,當我們把 table 當作?;蛘哧犃惺褂玫臅r候,容易犯錯,追加到 table 的末尾用的是 s[#s+1] = something,而不是 s[#s] = something,而且如果這個 something 是一個 nil 的話,會導致這一次壓棧(或者入隊列)沒有存入任何東西,#s 的值沒有變。如果 s = { 1, 2, 3, 4, 5, 6 },你令 s[4] = nil,#s 會令你“匪夷所思”地變成 3。

table.getn 獲取長度

取長度操作符寫作一元操作 #。字符串的長度是它的字節(jié)數(shù)(就是以一個字符一個字節(jié)計算的字符串長度)。

對于常規(guī)的數(shù)組,里面從 1 到 n 放著一些非空的值的時候,它的長度就精確的為 n,即最后一個值的下標。如果數(shù)組有一個“空洞”(就是說,nil 值被夾在非空值之間),那么 #t 可能是指向任何一個是 nil 值的前一個位置的下標(就是說,任何一個 nil 值都有可能被當成數(shù)組的結束)。這也就說明對于有“空洞”的情況,table 的長度存在一定的 不可確定性

local tblTest1 = { 1, a = 2, 3 }
print("Test1 " .. table.getn(tblTest1))

local tblTest2 = { 1, nil }
print("Test2 " .. table.getn(tblTest2))

local tblTest3 = { 1, nil, 2 }
print("Test3 " .. table.getn(tblTest3))

local tblTest4 = { 1, nil, 2, nil }
print("Test4 " .. table.getn(tblTest4))

local tblTest5 = { 1, nil, 2, nil, 3, nil }
print("Test5 " .. table.getn(tblTest5))

local tblTest6 = { 1, nil, 2, nil, 3, nil, 4, nil }
print("Test6 " .. table.getn(tblTest6))

我們使用 Lua 5.1 和 LuaJIT 2.1 分別執(zhí)行這個用例,結果如下:

# lua test.lua
Test1 2
Test2 1
Test3 3
Test4 1
Test5 3
Test6 1
# luajit test.lua
Test1 2
Test2 1
Test3 1
Test4 1
Test5 1
Test6 1

這一段的輸出結果,就是這么 匪夷所思。請問,你以后還敢在 Lua 的 table 中用 nil 值嗎?如果你繼續(xù)往后面加 nil,你可能會發(fā)現(xiàn)點什么。你可能認為你發(fā)現(xiàn)的是個規(guī)律。但是,你千萬不要認為這是個規(guī)律,因為這是錯誤的。

不要在 Lua 的 table 中使用 nil 值,如果一個元素要刪除,直接 remove,不要用 nil 去代替

table.concat (table [, sep [, i [, j ] ] ])

對于元素是 string 或者 number 類型的表 table,返回 table[i]..sep..table[i+1] ··· sep..table[j] 連接成的字符串。填充字符串 sep 默認為空白字符串。起始索引位置 i 默認為 1,結束索引位置 j 默認是 table 的長度。如果 i 大于 j,返回一個空字符串。

示例代碼

local a = {1, 3, 5, "hello" }
print(table.concat(a))              -- output: 135hello
print(table.concat(a, "|"))         -- output: 1|3|5|hello
print(table.concat(a, " ", 4, 2))   -- output:
print(table.concat(a, " ", 2, 4))   -- output: 3 5 hello

table.insert (table, [pos ,] value)

在(數(shù)組型)表 table 的 pos 索引位置插入 value,其它元素向后移動到空的地方。pos 的默認值是表的長度加一,即默認是插在表的最后。

示例代碼

local a = {1, 8}             --a[1] = 1,a[2] = 8
table.insert(a, 1, 3)   --在表索引為1處插入3
print(a[1], a[2], a[3])
table.insert(a, 10)    --在表的最后插入10
print(a[1], a[2], a[3], a[4])

-->output
3   1   8
3   1   8   10

table.maxn (table)

返回(數(shù)組型)表 table 的最大索引編號;如果此表沒有正的索引編號,返回 0。

當長度省略時,此函數(shù)通常需要 O(n) 的時間復雜度來計算 table 的末尾。因此用這個函數(shù)省略索引位置的調用形式來作 table 元素的末尾追加,是高代價操作。

示例代碼

local a = {}
a[-1] = 10
print(table.maxn(a))
a[5] = 10
print(table.maxn(a))

-->output
0
5

此函數(shù)的行為不同于 # 運算符,因為 # 可以返回數(shù)組中任意一個 nil 空洞或最后一個 nil 之前的元素索引。當然,該函數(shù)的開銷相比 # 運算符也會更大一些。

table.remove (table [, pos])

在表 table 中刪除索引為 pos(pos 只能是 number 型)的元素,并返回這個被刪除的元素,它后面所有元素的索引值都會減一。pos 的默認值是表的長度,即默認是刪除表的最后一個元素。

示例代碼

local a = { 1, 2, 3, 4}
print(table.remove(a, 1)) --刪除速索引為1的元素
print(a[1], a[2], a[3], a[4])

print(table.remove(a))   --刪除最后一個元素
print(a[1], a[2], a[3], a[4])

-->output
1
2   3   4   nil
4
2   3   nil nil

table.sort (table [, comp])

按照給定的比較函數(shù) comp 給表 table 排序,也就是從 table[1] 到 table[n],這里 n 表示 table 的長度。 比較函數(shù)有兩個參數(shù),如果希望第一個參數(shù)排在第二個的前面,就應該返回 true,否則返回 false。 如果比較函數(shù) comp 沒有給出,默認從小到大排序。

示例代碼

local function compare(x, y) --從大到小排序
   return x > y         --如果第一個參數(shù)大于第二個就返回true,否則返回false
end

local a = { 1, 7, 3, 4, 25}
table.sort(a)           --默認從小到大排序
print(a[1], a[2], a[3], a[4], a[5])
table.sort(a, compare) --使用比較函數(shù)進行排序
print(a[1], a[2], a[3], a[4], a[5])

-->output
1   3   4   7   25
25  7   4   3   1

table 其他非常有用的函數(shù)

LuaJIT 2.1 新增加的 table.newtable.clear 函數(shù)是非常有用的。前者主要用來預分配 Lua table 空間,后者主要用來高效的釋放 table 空間,并且它們都是可以被 JIT 編譯的。具體可以參考一下 OpenResty 捆綁的 lua-resty-* 庫,里面有些實例可以作為參考。

上一篇:FFI下一篇:與其他 location 配合