【Lua学习笔记】Lua进阶——Table,迭代器
文章目录
- 官方唯一指定数据结构--table
- table的一万种用法
- 字典和数组
- 迭代器
- ipairs()
- pairs()
- 回到Table
在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点,本文将补充Lua的一些进阶知识
官方唯一指定数据结构–table
在上篇文章的最后,我们指出通过查询_G的字符索引,发现table.insert实际上是一个名为table的table结构里的索引指向的函数
实际上不仅它,所有的函数,模块,全局变量,元表
我不知道作者是出于什么样的心理活动写出的Lua,但确实让我这个初学者大为震撼。
(以下内容摘抄自Lua语言:基础知识)
但是作为Lua中唯一的数据结构,table还是很万能的:
- 它可以用任何类型作索引,不止number和string,也可以使用其他类型(甚至function和table)
- Table功能强大,它即可以用作字典,也可以用作数组,配合元表机制还可以模拟面向对象。
- Lua的很多基础设施,比如模块,全局变量,元表,都是基于table实现的。
table的一万种用法
字典和数组
-- 当成字典使用
local t = {a = 1,b = true,c = "abc",
}
-- 当成数组使用
local t2 = {1, "aa", false}
这两种都是很自然的用法,既能作为字典,又能作为数组
但是它也可以同时表示字典和数组
local t3 = {1, 2, 3,a = "aaa",b = "bbb",
}
print(t3[1])
print(t3.a)
结果:
1
aaa
需要注意的是其中的数组和字典是以两种不同的方式存储的local t3 = {a = "aaa",1, 2,b = "bbb",3
}
print(t3.a)
print(t3[1])
print(t3[3])
结果:
aaa
1
3
从上述例子我们能看到,数字索引直接访问了数组元素略过了键值对,
使用键值对的key名才能访问字典中对应的值
使用下列模式使得它们在格式上更通用
local t3 = {[1] = 1, [2] = 2, [3] = 3,["a"] = "aaa",["b"] = "bbb",
}
但是上述只是个例子,在实践中,我们最好不混用字典和数组,这常常会引发混乱的问题。而从设计的角度看,它违反了单一职责原则,比如空Table就存在着二义性,如果它是空的,那么请问这种情况下它是数组还是字典?这往往会导致使用时的各种问题,例子请看下文迭代器。
迭代器
虽然迭代器并不属于Table的知识,但我认为在此处插入讲一下是比较合适的。主要就是pairs和ipairs的区别
ipairs()
返回三个值(迭代函数、表 t
以及 0
), 如此,以下代码
for i,v in ipairs(t) do body end
将迭代键值对 (1,t[1]) ,(2,t[2]), ...
,直到第一个空值。
例子:
local tab = {23,35,[3] = 45,78,[8] = 101,nil,80
}for k,v in ipairs(tab) doprint(k..":"..v)
end
输出:
1:23
2:35
3:78
在上述例子中,ipairs遍历了数组,但在nil时停下,实际上这个table的结构应该是这样:
local tab: {[1]: integer = 23,[2]: integer = 35,[3]: integer = 45|78,[4]: nil,[5]: integer = 80,[8]: integer = 101,
}
来个更混乱的例子
local tab = {23,35,[3] = 45,78,["a"] = 5,[8] = 101,[3] = nil,1212,nil,80,["b"]=nil
}for k, v in ipairs(tab) doprint(k .. ":" .. v)
end
输出:
1:23
2:35
3:78
4:1212这是它的实际结构
local tab: {["a"]: integer = 5,["b"]: nil,[1]: integer = 23,[2]: integer = 35,[3]: integer|nil = 45|78,[4]: integer = 1212,[5]: nil,[6]: integer = 80,[8]: integer = 101,
}
可以看出ipair只会遍历数字key名的元素(也就是数组类型),并且当碰到nil时停下,而其他字典类型会被无视
而ipair会有三个返回值,分别是迭代函数,表,index。让我们看看这三个值在迭代器中是如何迭代的:
print("---index=0---")
funcA ,table, index =ipairs(tab)
for k, v in funcA, table, index doprint(k .. ":" .. v)
end
print("---index=1---")
for k, v in funcA, table, index+1 doprint(k .. ":" .. v)
end输出:
---index=0---
1:23
2:35
3:78
4:1212
---index=1---
2:35
3:78
4:1212
从上述例子中可以看到,index实际上代表了起始序列,当index=0,对应从table的数组标签[1]开始,当index=1,则从[2]开始
如果数组里有负数和0呢?
local tab = {[0] = 1,2,[-1] = 3,4,5,[5] = 6,
}
for k, v in ipairs(tab) doprint(k .. ":" .. v)
end
输出:
1:2
2:4
3:5
实际的table结构
local tab: {[0]: integer = 1,[1]: integer = 2,[-1]: integer = 3,[2]: integer = 4,[3]: integer = 5,[5]: integer = 6,
}
可以看到,0和负数都被ipairs自动略过了,有意思的是由于[4]没有定义,因此被认为是nil而停止了迭代。
总结:ipairs会略过数组的0和负数索引,以及其他字典索引,从数组的[1]索引开始迭代(对应index=0),顺序迭代直到某个索引不存在或其对应的值为空时结束
pairs()
让我们把上述几个例子用pairs遍历一下
local tab = {23,35,[3] = 45,78,[8] = 101,nil,80
}for k,v in pairs(tab) doprint(k..":"..v)
end
输出:
1:23
2:35
3:78
5:80
8:101
table的结构是这样:
local tab: {[1]: integer = 23,[2]: integer = 35,[3]: integer = 45|78,[4]: nil,[5]: integer = 80,[8]: integer = 101,
}
可以看到重复定义的元素值还是选择了后者,并且nil被无视了
local tab = {["b"]=8,[0] = 1,2,[-1] = 3,4,5,[5] = 6,["a"]=7,
}
for k, v in pairs(tab) doprint(k .. ":" .. v)
end
输出:
1:2
2:4
3:5
0:1
b:8
a:7
-1:3
5:6
实际的table结构
local tab: {[0]: integer = 1,[1]: integer = 2,[-1]: integer = 3,[2]: integer = 4,[3]: integer = 5,[5]: integer = 6,["a"]: integer = 7,["b"]: integer = 8,
}
有意思的是pairs是先按数字顺序输出了数组,然后碰到了不存在的索引[4],随后输出了0,b,a,-1。顺序十分诡异,最后才输出了[5]。我不知道为什么这样输出,但是这种输出方式也侧面证明了数组不要和字典一起定义!
总结:
ipairs会略过数组非正数索引,以及其他字典索引,从数组的[1]索引开始迭代(对应index=0),顺序迭代直到某个索引不存在或其对应的值为空时结束。
pairs可以输出table内除了nil以外的所有元素。但是数组和字典的混合以及带有非正值数字索引的元素输出方式会很诡异。
所以别用非正数索引(实际上非正索引应当称为自定义索引),也别把数组和字典定义在一个table里!
回到Table
table将key的值设为nil,它的真实含义是删除掉这个key,这和其他脚本很不一样,也可能引发一些问题,比如看下面例子:
local t = {1, 2, nil, 4}
print(#t) ---> 4
for k, v in ipairs(t) do print(v) end ---> 1 2
for k, v in pairs(t) do print(v) end ---> 1 2 4
for i = 1, #t do print(t[i]) end ---> 1 2 nil 4
可以看到使用迭代器是直接无视nil的,但使用for遍历会得到nil,我们本意是想删除这个元素,但是它依然存在于table中
那么nil不等于删除吗?请看下列的例子:
local t = {1, 2, nil, nil, 5}
print(#t) --> 5
t = {[1]=1, [2]=2, [3]=nil, [4]=nil, [5]=4}
print(#t) --> 2
直接定义nil时,nil是会计入table的长度的。但主动定义键值对时nil不会计入table的长度。因此当我们定义table时,应当以键值对的方式定义
过分吗?还有更过分的
a = { [1] = 1, [2] = 2, [5] = 5, [6] = 6 }
print(#a) -->2
b = { [1] = 1, [2] = 2, [4] = 4, [5] = 5, [6] = 6 }
print(#b) -->6
c = { [1] = 1, [2] = 2, [4] = 4, [5] = 5, [6] = 6, [9] = 9 }
print(#c) -->6
d = { [1] = 1, [2] = 2, [4] = 4, [5] = 5, [6] = 6, [8] = 8, [9] = 9 }
print(#d) -->6
发现了吗?键值对形式存储时,中间如果隔了一个nil,那么长度会接上;如果隔了两个nil长度就会断开
???
🧠
(O.o)>
相关文章:

【Lua学习笔记】Lua进阶——Table,迭代器
文章目录 官方唯一指定数据结构--tabletable的一万种用法字典和数组 迭代器ipairs()pairs() 回到Table 在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点,本文将补充Lua的一些进阶知识 官方唯一指定数据结构–table 在上篇文章的最后,我们指出…...

重庆市北斗新型智慧城市政府项目
技术栈:使用vue2JavaScriptElementUIvuexaxiosmapboxcesium 项目描述:重庆市北斗新型智慧城市政府项目是基于千寻孪界开发的一款智慧城市项目,包含车辆实时位置定位,智能设备的报警,基础设施的部设等等功能 工作内容&a…...

FANUC机器人SRVO-217故障报警原因分析及参考解决办法
FANUC机器人SRVO-217故障报警原因分析及参考解决办法 如下图所示,示教器提示:SRVO-217紧急停止电路板未找到, 查阅手册可以看到以下的报警说明: 故障原因: 通电时未能识别紧急停止电路板或者增设的安全I/O装置。连接有多个安全I/O装置的系统中,在报警信息的最后,会显示发…...

统信UOS安装mysql数据库(mariadb)-统信UOS安装JDK-统信UOS安装nginx(附安装包)
统信UOS离线全套安装教程(手把手教程) 银河麒麟的各种离线全套安装教程: https://blog.csdn.net/ACCPluzhiqi/article/details/131988147 1.统信UOS桌面系统安装mysql(mariadb) 2.统信UOS桌面系统安装JDK 3.统信UOS桌…...

上门小程序开发|上门服务小程序|上门家政小程序开发
随着移动互联网的普及和发展,上门服务成为了许多人生活中的一部分。上门小程序是一种基于小程序平台的应用程序,它提供了上门服务的在线平台,为用户提供了便捷的上门服务体验。下面将介绍一些适合开发上门小程序的商家。 家政服务商家&am…...

1000道网络安全必备面试题合集,秋招金九银十必看!!!
以下为网络安全各个方向涉及的面试题,星数越多代表问题出现的几率越大,祝各位都能找到满意的工作。 注:本套面试题,已整理成pdf文档,但内容还在持续更新中,因为无论如何都不可能覆盖所有的面试问题&#x…...

从0-1实现简易Raft分布式共识算法
一、Raft前置简介 Raft目前是最著名的分布式共识性算法,被广泛的应用在各种分布式框架、组件中,如Redis、RocketMq、Kafka、Nacos(CP)等 根据Raft论文,可将Raft拆分为如下4个功能模块: 领导者选举日志同…...

Spring 创建和使用
Spring 是⼀个包含了众多⼯具⽅法的 IoC 容器。既然是容器那么它就具备两个最基本的功能: 将对象存储到容器(Spring)中; 从容器中将对象取出来。 在 Java 语⾔中对象也叫做 Bean 1.创建 Spring 项目 接下来使⽤ Maven ⽅式来创…...

Javadoc comment自动生成
光标放在第二行 按下Alt Shift j 下面是Java doc的生成 Next Next-> Finish...

vue3 +ts 报错 index.vue 不是模块
那是因为index.vue中创建了一个空的script标签,而且语法使用的是ts语法。vue-cli会用ts语法解析和校验 如果是无状态组件,删掉 如果是有状态组件,导出该组件的实例 去掉null的script后:...

win10 hadoop报错 unable to load native-hadoop library
win10 安装hadoop执行hdfs -namenode format 和运行hadoop的start-all报错 unable to load native-hadoop library 验证: hadoop checknative -a 这个命令返回都是false是错的 返回下图是正确的 winutils: true D:\soft\hadoop-3.0.0\bin\winutils.exe Native li…...

前端(九)——探索微信小程序、Vue、React和Uniapp生命周期
🙂博主:小猫娃来啦 🙂文章核心:探索微信小程序、Vue、React和Uniapp生命周期 文章目录 微信小程序、Vue、React和Uniapp的基本定义和应用领域微信小程序生命周期生命周期概述页面生命周期应用生命周期组件和API的生命周期钩子 Vu…...

MyBatis查询数据库(2)
目录 前言🍭 一、增删查改操作 1、查 Ⅰ、mapper接口: Ⅱ、UserMapper.xml 查询所有用户的具体实现 SQL: Ⅲ、进行单元测试 2、增、删、改操作 Ⅰ、增 添加用户 添加用户并且返回自增 id Ⅱ、改 根据id修改用户名 开启 MyBatis …...

Jenkins构建完成后发送消息至钉钉
钉钉群的最终效果: 1、jenkins安装DingTalk插件,安装完成后重启 2、配置钉钉插件 参考官网文档:快速开始 | 钉钉机器人插件 系统管理 拉到最下面,可以看到钉钉配置 按照如下配置钉钉机器人 配置完成可以点击测试按钮࿰…...

从浏览器输入url到页面加载(六)前端必须了解的路由器和光纤小知识
前言 上一章我们说到了数据包在网线中的故事,说到了双绞线,还说到了麻花。这一章继续沿着这条线路往下走,说一些和cdn以及路由器相关,运营商以及光纤相关的小知识,前端同学应该了解一下的 目录 前言 1. CDN和路由器…...
C语言假期作业 DAY 06
题目 一、选择题 1、以下叙述中正确的是( ) A: 只能在循环体内和 switch 语句体内使用 break 语句 B: 当 break 出现在循环体中的 switch 语句体内时,其作用是跳出该 switch 语句体,并中止循环体的执行 C: continue 语句的作用是&…...
[nlp] tokenizer加速:fast_tokenizer=True
fast_tokenizer 是一个布尔值参数,用于指定是否使用快速的 tokenizer。在某些情况下,使用快速的 tokenizer 可以加快模型训练和推理速度。如果 fast_tokenizer 参数为 True,则会使用快速的 tokenizer;否则,将使用默认的 tokenizer。 快速的 tokenizer 通常使用一些技巧来减…...

基于OpenCV solvePnP函数估计头部姿势
人脸识别 文章目录 人脸识别一、姿势估计概述1、概述2、姿态估计3、在数学上表示相机运动4、姿势估计需要什么5、姿势估计算法6、Levenberg-Marquardt 优化 二、solvePnP函数1、函数原型2、参数详解 三、OpenCV源码1、源码路径 四、效果图像示例参考链接 一、姿势估计概述 1、…...

STC12C5A系列单片机内部 EEPROM 的应用
参考范例程序。 eeprom.c #include "eeprom.h"/*---------------------------- Disable ISP/IAP/EEPROM function Make MCU in a safe state ----------------------------*/ void IapIdle() {IAP_CONTR 0; //Close IAP functionIAP_CMD 0; …...

搭建测试平台开发(一):Django基本配置与项目创建
一、安装Django最新版本 1 pip install django 二、创建Django项目 首先进入要存放项目的目录,再执行创建项目的命令 1 django-admin startproject testplatform 三、Django项目目录详解 1 testplatform 2 ├── testplatform # 项目的容器 3 │ ├──…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...

大型活动交通拥堵治理的视觉算法应用
大型活动下智慧交通的视觉分析应用 一、背景与挑战 大型活动(如演唱会、马拉松赛事、高考中考等)期间,城市交通面临瞬时人流车流激增、传统摄像头模糊、交通拥堵识别滞后等问题。以演唱会为例,暖城商圈曾因观众集中离场导致周边…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

解读《网络安全法》最新修订,把握网络安全新趋势
《网络安全法》自2017年施行以来,在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂,网络攻击、数据泄露等事件频发,现行法律已难以完全适应新的风险挑战。 2025年3月28日,国家网信办会同相关部门起草了《网络安全…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG
TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码:HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...
TJCTF 2025
还以为是天津的。这个比较容易,虽然绕了点弯,可还是把CP AK了,不过我会的别人也会,还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...

MLP实战二:MLP 实现图像数字多分类
任务 实战(二):MLP 实现图像多分类 基于 mnist 数据集,建立 mlp 模型,实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入,可视化图形数字; 2、完成数据预处理:图像数据维度转换与…...