【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 │ ├──…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...
docker 部署发现spring.profiles.active 问题
报错: org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...

tauri项目,如何在rust端读取电脑环境变量
如果想在前端通过调用来获取环境变量的值,可以通过标准的依赖: std::env::var(name).ok() 想在前端通过调用来获取,可以写一个command函数: #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
电脑桌面太单调,用Python写一个桌面小宠物应用。
下面是一个使用Python创建的简单桌面小宠物应用。这个小宠物会在桌面上游荡,可以响应鼠标点击,并且有简单的动画效果。 import tkinter as tk import random import time from PIL import Image, ImageTk import os import sysclass DesktopPet:def __i…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...

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

基于谷歌ADK的 智能产品推荐系统(2): 模块功能详解
在我的上一篇博客:基于谷歌ADK的 智能产品推荐系统(1): 功能简介-CSDN博客 中我们介绍了个性化购物 Agent 项目,该项目展示了一个强大的框架,旨在模拟和实现在线购物环境中的智能导购。它不仅仅是一个简单的聊天机器人,更是一个集…...