Lua基础(七)表

一  表的特点

lua查找元表的过程

table是Lua'最复杂最强大'的数据结构,Lua本身并'不是面向对象'语言,面向对象中毒比较深的程序员'可以借助'table"完美地模拟"面向对象编程

+++++++++++++++'分割线'+++++++++++++++

1)表'table'是Lua语言中'最主要'-->'唯一'的强大'数据结构'

2)Lua语言以一种'简单、统一、高效'的方式表示'数组、集合、记录'和其它数据结构-->包括'function'和'table'

3)Lua语言中'表本质'是一种'辅助数组',类似awk中的"关联数组",数组的索引可以是'数字'、'字符串'、其它任意类型的值-->'nil除外'

4)table 的默认'初始索引'以' 1 '开始

5)table '不会固定长度'大小,有新数据插入时长度会'自动增长'

6)table 所有'元素之间',总是用逗号',' 隔开

7)表是一种'动态分配'的对象,程序只能'操作执行表'的引用('指针')

8)table 的变量只是一个'地址引用',对 table 的操作不会产生数据影响

二  表的操作

(1)构造器表达式创建表

a = {}  -->'空构造器'创建'空表'

注意:'local a = {}' 与 'a = {}'的差异性

+++++++++++++"解读"+++++++++++++

local a = {}   --> a是一个'局部变量'

type(a)        --> a是另一个'新'的"全局"变量 --> 所以是'nil'

(2)初始化

方式1:添加元素初始化

备注: a[k]形式'赋值' --> k是'变量' --> '实际等价' a["value"] = 10

补充: 常见的'三种'形式赋值: a.k = 10  <='等价'=>  a["k"] = 10 、a[var] = 100

小结:表永远是'匿名的','表本身'和'保存表的变量'之间'没有固定'的关系

说明:对于一个表而言,当程序中'不再有指向它的引用-->引用计数'时,垃圾收集器会'最终删除'这个表并重用其占用的内存

方式2:构造器初始化表

++++++++++++++++++'可以理解为数组初始化'++++++++++++++++++

days = {"Monday","Tueday","Wednesday","Thursday","Friday","Saturday","Sunday"} -->'简写'

等价: days = { [1]="Monday",[2]="Tueday","Wednesday" ...} --> "复杂形式"

特点:提前判断'表的大小',所以'运行速度更快'

备注: 索引是'数字',默认["数组"]第一个index是'1'

方式3:初始化记录式

a = { x = 1, y = 9} ["简写"]  <--> {["x"] = 1, ["y"] = 9} ["复杂"]

+++++++'等价方式'+++++++

a = {};a.x = 1 --> a["x"] = 1;a.y = 9

约定: key如果是'字符串string','声明'和'调用'最好不要加"双引号"

方式4:混用记录式和列表式

说明: 通过创建'嵌套表'和'构造器'构建更加复杂的'数据结构'

备注: 这种方式不能使用'负数'索引初始化元素

补充: table的'元素'可以是'任意'的数据结构,这里'只涉猎'table、键值对

方式5:通用方式

说明:'任何元素'来作为'索引'

operations = { ["+"] = "add", ["-"] = "sub", ["*"] = "mul", ["/"] = "div"}

说明:上述的四种方式是该种'通用方式'的特殊形式

 (3)表索引

重点: 同一个'表中存储的值'可以具有'不同的类型索引',并可以'按需增长'以容纳'新'的元素

1)'未经初始化'的表元素为'nil'

2)将nil'赋值给表元素'可以将其'删除'

(4)两种方式引用(重点

1)点分形式-->'a.name'-->清晰说明了'表是被当作结构体'使用的

备注:此时表是由'固定的、预先定义'的键组成的'集合'

2)形如a["name"]的字符串索引形式则说明了表可以使用'任意字符'作为键

+++++++++++'二者辨析'+++++++++++

1)a.x代表的含义是a["x"],即由字符串"x"索引的表

2)a[x]则是置由'变量x'对应的值索引的表

需求:当不能确定表'索引的真实数据类型'时,可以用'显式的'类型转换,避免在程序中引入'BUG'

a[tonumber(i)] --> 'number-->数值类型的键'

++++++++++++++++'分割线'++++++++++++++++

'整数和负类型'的'表索引'不存在上述问题,不需要'显式'转化

细节: 任何能够'被转化为整数的浮点数'都会被'转换成整数型'

(5)数组、列表、序列

+++++++++'可以理解为二者等价'+++++++++

数组 --> 'java' --> 整数为索引,区别于其它语言,从'1'开始 -->实际只需要'索引是正整数'即可
 
列表 --> 'python'

+++++++++++++++'序列概念'+++++++++++++++

序列 --> 列表中'所有的元素'都不为'nil',也即列表中'不存在'空洞'hole' -->在列表的基础上继续'升华'

说明: 如果明确是'序列',则可以通过'#'来统计'列表的长度'

①  禁止不连续数组表求长度

hole --> 出现'空洞' --> #arrary '遇nil'即'停止'统计

②  打印序列内容

备注:  数组'遍历'的时候'有用'  ->'#table' -->统计个数

③  序列的几个常用的操作

④  补充

Lua语言中: 一个'为nil的字段'和一个'不存在的元素'没有区别

+++++++++++'解释'+++++++++++

a = {1, 2, nil, nil}  '等价' a + {1, 2}  --> '长度为3'

(6)遍历表

①  pairs迭代器遍历表中的键值对

++++++++++'特点'++++++++++

1)受限于表在Lua语言中的'底层实现机制',遍历过程中元素出现的'顺序可能是随机(random)的'

备注:所谓的随机'具体表现'为每次打印都可能'不同';'但是'遍历的过程中每个元素'会且只会出现一次'

遍历结果'result'是'随机的' --> 多次'遍历的结果'不一样

②  ipairs迭代器遍历列表

++++++++++++++多次执行的'结果'++++++++++++++

1)对于'列表',执行该脚本的结果是'幂等的',始终保持着'顺序'

2)'ipairs方式'在迭代的过程中,遇到'hole-->即:nil值'则退出

二者的区别

参考博客

+++++++++++++'区别在于'+++++++++++++

核心:遍历'列表'的时候二种方式都可以'按照顺序遍历' -->多次执行顺序结果是一致的-->'幂等性'

1)pairs可以遍历到表中所有的key,对于'key的类型没有要求',遇到'nil时可以跳过-->jump',不会影响后面的遍历

2)ipairs遍历时'只能取key为整数值',遇到nil时'终止-->end'遍历 -->所以只适合'列表[数组]'-->'index为正整数'

③  数值型for循环

说明: 这种方式只针对'序列'

④  最佳实践

1)如果'是序列'且需要'顺序输出-->index的顺序',优先采用'ipairs'和'for数值循环'

2)如果是'一般table-->非列表',并且'没有顺序'的需求,采用'pairs'进行遍历

三   表标准库

说明: 表标准库提供了'操作列表'和'序列'的一些常用函数

①  insert

特点:向'序列'的'指定位置(pos)插入值为value'的一个元素,'pos参数可选','不指定'位置,则默认在序列的'末尾'

②  remove

+++++++++++++++'remove特点'+++++++++++++++

1)删除指定位置'pos'的元素

2)返回'return'-->序列'指定位置'的元素

备注1: pos位置'后'的元素会'被前移',pos参数可选('options')

备注2: 默认为table长度,即从'最后一个元素删起'

++++++++++++'区别'++++++++++++

'array[index] =nil' 和 'table.remove(array,index)'的区别

③  move

move讲解

Lua(>='5.3引入')中的table.move

+++++++++++++'分割线'+++++++++++++

原型:table.move(a1,f,e,t[,a2])
函数作用: 把表a1中从下标f到e的value移动到表a2中,位置为a2下标从t开始
函数参数: 表a1,a1下标开始位置f,a1下标结束位置e,t选择移动到的开始位置(如果没有a2,默认a1的下标)

④  concat

concat: 输出一个列表中'元素连接成的字符串'

⑤  sort

table.sort()函数对给定的table进行'升序排序'

⑥  getn

当我们获取 table 的长度的时候无论是'使用 #' 还是 'table.getn' 其都会在'索引中断-->不连续'的地方停止计数,而导致'无法正确取得 table 的长度'

 ⑦  maxn

table.maxn 在 'Lua5.2 之后'该方法已经'不存在了'-->'lua5.3'中我们定义了 'table_maxn' 方法来实现,获取 table 中的'最大值'

++++++++++'lua5.3'的自定义实现++++++++++

function table_maxn(t)
  local mn = nil
  for k, v in pairs(t) do
    是否'中断'或者'最后'一个元素
    if(mn==nil) then
      mn=v
    end
    if mn < v then
      mn = v
    end
  end
  return mn
end

链接

四  lua操作table注意事项

1)最好不要'数组'和hash'混用',否则'#取长度'会乱七八糟

2)数组中'不要存储nil值'

3)使用table.remove,'不要使用置nil'

五  常见的需求

①  判断table中是否包含某个value

-- 判断table中是'否包含某个value'

function is_include(value, tab)
    for k,v in pairs(tab) do
      if v == value then
          return true
      end
    end
    return false
end

②  判断lua table是否为空表

判断过程

需求:lua table中如何'判断为空表'  --> '靠lua内置的next函数'

if next(a) == nil then

特点:next其实就是'pairs遍历table时'用来取下一个内容的函数

+++++++++++'最佳实践-->封装成函数'+++++++++++

1)在项目的'module中最好封装'一下,免得module'本地也有next函数',于是封装后'判断'的lua table是否为空的函数如下

function table_is_empty(t)
     return _G.next( t ) == nil
end

lua中神奇的表

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值