openresty开发系列19--lua的table操作

Lua中table内部实际采用哈希表和数组分别保存键值对、普通值;下标从1开始

不推荐混合使用这两种赋值方式。

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

一)table.getn 获取长度

相关于取长度操作符写作一元操作 #。

字符串的长度是它的字节数(就是以一个字符一个字节计算的字符串长度)。
对于常规的数组,里面从 1 到 n 放着一些非空的值的时候,它的长度就精确的为 n,即最后一个值的下标。
local tblTest1 = { 1, a = 2, 3 }
print("Test1 " .. table.getn(tblTest1))
此table的长度为2,可是明明是三个数值啊,这里要说明一下,getn 只能执行数值型的table,即数值索引的值.
忽略哈希值类型的键值对map,即不包含字符索引值

local tblTest1 = { b=1, a = 2, 3 }
print("Test1 " .. table.getn(tblTest1))    #输出长度为1

local tblTest1 = { b=1, a = 2, c=3 }
print("Test1 " .. table.getn(tblTest1))    #输出长度为0

local tblTest1 = { 1, 2, 3 }
print("Test1 " .. table.getn(tblTest1))    #输出长度为3

在有个地方说明一下
--此table 虽然有[3]=6,也是数组型,但是不连续的,缺少了2的索引,所以输出长度为1

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

--此table 数值索引是连续 到2,所以输出长度为2
local tblTest1 = { [2] = 6,c = 1, a = 2, 3 }
print("Test1 " .. table.getn(tblTest1))

=============================
获取table长度,不区分数组和键值对

function table_length(t)
  local leng=0
  for k, v in pairs(t) do
    leng=leng+1
  end
  return leng;
end

=================
特殊说明:

如果数组有一个"空洞"(就是说,nil 值被夹在非空值之间),那么 #t 可能是指向任何一个是 nil 值的前一个位置的下标(就是说,任何一个 nil 值都有可能被当成数组的结束)。
这也就说明对于有"空洞"的情况,table 的长度存在一定的 不可确定性。

关于nil的特别说明
local tblTest2 = { 1,nil,2}
对一个table中有nil值 取长度,会有很多不确定性,不同的luajit版本输出的结果也不一样

不要在 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, " ", 2, 4))   -- output: 3 5 hello
print(table.concat(a, " ", 4, 2))   -- output:

在介绍string字符串那边有个字符串拼接,是用.. 这个符号进行的
local str = "a" .. "b" .. "c"..........................  推荐用concat

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

在(数组型)表 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.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])

local a = { 1, 7, 3, 4, 25}
table.sort(a)           --默认从小到大排序

print(a[1], a[2], a[3], a[4], a[5])
-->output
1   3   4   7   25

按照给定的比较函数 comp 给表 table 排序,也就是从 table[1] 到 table[n],这里 n 表示 table 的长度。
比较函数有两个参数,如果希望第一个参数排在第二个的前面,就应该返回 true,否则返回 false。
如果比较函数 comp 没有给出,默认从小到大排序。

local function compare(x, y) --从大到小排序
   return x > y         --如果第一个参数大于第二个就返回true,否则返回false
end

table.sort(a, compare) --使用比较函数进行排序
print(a[1], a[2], a[3], a[4], a[5])

-->output
25  7   4   3   1

六)table.maxn (table)

返回(数组型)表 table 的最大索引编号;如果此表没有正的索引编号,返回 0。
local a = {}
a[-1] = 10
print(table.maxn(a))
a[5] = 10
print(table.maxn(a))

-->output
0
5

七)table 判断是否为空

大家在使用 Lua 的时候,一定会遇到不少和 nil 有关的坑吧。
有时候不小心引用了一个没有赋值的变量,这时它的值默认为 nil。如果对一个 nil 进行索引的话,会导致异常。
如下:
local person = {name = "Bob", sex = "M"}
-- do something
person = nil
-- do something
print(person.name)

报错person为nil了
然而,在实际的工程代码中,我们很难这么轻易地发现我们引用了 nil 变量。
因此,在很多情况下我们在访问一些 table 型变量时,需要先判断该变量是否为 nil,例如将上面的代码改成:

local person = {name = "Bob", sex = "M"}
-- do something
person = nil
-- do something
if person ~= nil then
  print(person.name)
else
  print("person 为空")
end

对于简单类型的变量,我们可以用 if (var == nil) then 这样的简单句子来判断。
我们如果要判断table类型的对象是否为空,那如何判断呢?

我们思考一下,判断table是否为空有两种情况:

第一种table对象为nil;
第二种table对象为{},代表没有键值对,但不为nil。

那么我们一般的判断逻辑就应该是 table == nil  或者 table的长度为0  就表示为空
下面我们看看以下例子:
local a = {}
local b = {name = "Bob", sex = "Male"}
local c = {"Male", "Female"}
local d = nil

if a == nil then
    print("a == nil")
end

if b == nil then
    print("b == nil")
end

if c == nil then
    print("c == nil")
end

if d== nil then
    print("d == nil")
end
 
if next(a) == nil then
    print("next(a) == nil")
end

if next(b) == nil then
    print("next(b) == nil")
end

if next(c) == nil then
    print("next(c) == nil")
end

以上有几个注意点,涉及到table类型的长度
(#a)   --"#"表示为获取table类型的长度,类似table.getn()
因为a为{},所以长度为0.

我们再看(#b) ,依然输出的是0,但b是有值的啊。

我们再看(#c),输出的是2,这个是怎么回事。这里就是之前在table类型的课程中已经介绍的获取table的长度,
只是获取的是 数组型的长度,不包含map型的。

我们再往下看 if a == nil then  在判断 a是否为nil,明显a不为nil
if next(a) == nil then中的next是什么意思呢?

next (table [, index])
功能:允许程序遍历表中的每一个字段,返回下一索引和该索引的值。
参数:table:要遍历的表
   index:要返回的索引的前一索中的号,当index为nil[]时,将返回第一个索引的值,
      当索引号为最后一个索引或表为空时将返回nil
next(a) 就是返回第一个索引的值,a的第一个索引是没有值的,那么next(a) 就为nil
所以next方法经常用来判断 table中是否有值。
下面的语句相信大家就能看懂了。
综合以上代码,我们判断table是否为空,就不能简单的判断table长度是否为0,而是判断索引值。

所以要判断table是否为空应该按照以下进行判断

function isTableEmpty(t)
    return t == nil or next(t) == nil
end

八)ipairs和pairs的区别

为了看出两者的区别,首先定义一个table:
a={"Hello","World";a=1,b=2,z=3,x=10,y=20;"Good","Bye"}  
for i, v in ipairs(a) do
    print(v)
end
输出的结果是:
Hello
World
Good
Bye

可见ipairs并不会输出table中存储的键值对,会跳过键值对,然后按顺序输出table中的值。
再使用pairs对其进行遍历:

for i, v in pairs(a) do
    print(v)
end

输出的结果是:
Hello
World
Good  
Bye   
1     
10    
2     
20    
3     
可见pairs会输出table中的值和键值对,并且在输出的过程中先按顺序输出值,再乱序输出键值对。
这是因为table在存储值的时候是按照顺序的,但是在存储键值对的时候是按照键的哈希值存储的,
并不会按照键的字母顺序或是数字顺序存储。
对于a来说,如果执行print(a[3]),输出的结果也会是Good。也就是说table并不会给键值对一个索引值。

也就是说ipairs只是按照索引值顺序,打印出了table中有索引值的数据,没有索引值的不管。
而pairs是先按照数组索引值打印,打印完成后再按照哈希键值对的键的哈希值打印它的值。

LuaJIT 2.1  新增加的 table.new 和 table.clear 函数是非常有用的。
前者主要用来预分配 Lua table 空间,后者主要用来高效的释放 table 空间,并且它们都是可以被 JIT 编译的。

转载于:https://www.cnblogs.com/reblue520/p/11433496.html

openresty开发系列19--lua的table操作相关推荐

  1. openresty开发系列27--openresty中封装redis操作

    openresty开发系列27--openresty中封装redis操作 在关于web+lua+openresty开发中,项目中会大量操作redis, 重复创建连接-->数据操作-->关闭 ...

  2. openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息

    openresty开发系列40--nginx+lua实现获取客户端ip所在的国家信息 为了实现业务系统针对不同地区IP访问,展示包含不同地区信息的业务交互界面.很多情况下系统需要根据用户访问的IP信息 ...

  3. openresty开发系列18--lua的字符串string操作

    openresty开发系列18--lua的字符串string操作 string的相关操作 1)string.upper(s) 接收一个字符串 s,返回一个把所有小写字母变成大写字母的字符串. prin ...

  4. openresty开发系列39--nginx+lua实现接口签名安全认证

    一)需求背景 现在app客户端请求后台服务是非常常用的请求方式,在我们写开放api接口时如何保证数据的安全, 我们先看看有哪些安全性的问题 请求来源(身份)是否合法? 请求参数被篡改? 请求的唯一性( ...

  5. openresty开发系列28--openresty中操作mysql

    openresty开发系列28--openresty中操作mysql Mysql客户端    应用中最常使用的就是数据库了,尤其mysql数据库,那openresty lua如何操作mysql呢?   ...

  6. openresty开发系列24--openresty中lua的引入及使用

    openresty开发系列24--openresty中lua的引入及使用 openresty 引入 lua 一)openresty中nginx引入lua方式 1)xxx_by_lua   ---> ...

  7. openresty开发系列20--lua的时间操作

    openresty开发系列20--lua的时间操作 在 Lua 中,函数 time.date 和 difftime 提供了所有的日期和时间功能. 在 OpenResty 的世界里,不推荐使用这里的标准 ...

  8. openresty开发系列15--lua基础语法4表table和运算符

    openresty开发系列15--lua基础语法4表table和运算符 lua中的表table 一)table (表) Table 类型实现了一种抽象的"关联数组".即可用作数组, ...

  9. openresty开发系列38--通过Lua+Redis 实现动态封禁IP

    openresty开发系列38--通过Lua+Redis 实现动态封禁IP 一)需求背景为了封禁某些爬虫或者恶意用户对服务器的请求,我们需要建立一个动态的 IP 黑名单.对于黑名单之内的 IP ,拒绝 ...

最新文章

  1. Redis 高级特性(3)—— 持久化及数据恢复
  2. 那个被捧上天的GPT-3要开始收费了!网友:天价,溜了溜了
  3. 面试经典:链表中倒数第k个结点?如何从大量数据中找出高频词?
  4. tableau实战系列(一)-轻松升级你的 Tableau Server
  5. 安卓手机可以连接斑马系统吗_Zebra斑马 StageNow 安卓系统移动设备快速部署工具...
  6. 在微信小程序中绘制图表(part2)
  7. C语言试题六十之请编写函数fun,计算并输出下列级数和:s=1/1*2+1/2*3+…+1/n(n+1)
  8. android sdk更新失败 解决方案
  9. 红帽linux中文系统下载iso,红帽子9.0版下载-redhat linux 9.0 iso下载 简体中文正式版-IT猫扑网...
  10. PHP PDF转图片:设置图像的色彩空间 RGBCMYK互转
  11. python卸载pip_python 怎样卸载pip
  12. X86服务器及“机架、塔式、刀片”三类服务器分类
  13. 基于java的URP教务系统爬虫实现
  14. 并发编程之AQS中的CLH队列
  15. ORACLE大数据查询
  16. 着色Shading(2)(着色的继续、管线和纹理映射)(笔记)
  17. 顾客信息表mysql_Qt5.5.0使用mysql编撰小软件源码讲解-顾客信息登记表_mysql
  18. 申请美国大学计算机专业,美国大学计算机专业申请全攻略
  19. 温度转换java小程序_利用easygui模块编写的华氏温度与摄氏温度转换的小程序
  20. linux命令行怎么结束进程,linux结束进程命令

热门文章

  1. python语言中整数1010的二进制表示_爱校码 - Python 语言基础二
  2. 派生类的拷贝构造【C++继承】
  3. (转)Fedora 17 安装完全指南
  4. 青少年计算机学奥林匹克大赛,2019年第36届全国青少年信息学奥林匹克竞赛获奖规则...
  5. 华为hcia H31-311 练习题
  6. Dubbo 3.0 前瞻:重塑 Spring Cloud 服务治理
  7. SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(优雅上下线)
  8. Google 宣布将 Istio 商标转移给 Open Usage Commons | 云原生生态周报 Vol. 57
  9. 阿里巴巴 Kubernetes 应用管理实践中的经验与教训
  10. 版本变迁_一本书遍览古今中外红楼梦版本变迁