【Lua学习笔记】Lua进阶——Table,迭代器

在这里插入图片描述

文章目录

  • 官方唯一指定数据结构--table
    • table的一万种用法
      • 字典和数组
  • 迭代器
    • ipairs()
    • pairs()
  • 回到Table

在【Lua学习笔记】Lua入门中我们讲到了Lua的一些入门知识点,本文将补充Lua的一些进阶知识


官方唯一指定数据结构–table

在上篇文章的最后,我们指出通过查询_G的字符索引,发现table.insert实际上是一个名为table的table结构里的索引指向的函数

实际上不仅它,所有的函数,模块,全局变量,元表

😅😅😅都 是 T A B L E😅😅😅

我不知道作者是出于什么样的心理活动写出的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)>


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/12333.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第九十四回 如何打造一个网络框架

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了"如何mock数据"相关的内容,本章回中将介绍如 何打造一个网络框架闲话休提,让我们一起Talk Flutter吧。 概念介绍 最近在项目中使用dio处理网络相关的内容,有些地方的代…

Mybatis使用collection映射一对多查询分页问题

场景&#xff1a;页面展示列表&#xff0c;需要查询多的字段&#xff0c;和一的字段。并且还要分页。 这时候直接想到的是手写sql。 /*** 标签*/private List<BasicResidentTags> tags;Data TableName("basic_resident_tags") public class BasicResidentTag…

SpringCloud微服务实战——搭建企业级开发框架(五十三):微信小程序授权登录增加多租户可配置界面

GitEgg框架集成weixin-java-miniapp工具包以实现微信小程序相关接口调用功能&#xff0c;weixin-java-miniapp底层支持多租户扩展。每个小程序都有唯一的appid&#xff0c;weixin-java-miniapp的多租户实现并不是以租户标识TenantId来区分的&#xff0c;而是在接口调用时&#…

C#如何使用SQLite数据库?

文章目录 0.引言1.SQLite工具准备2.创建窗体项目并添加SQLite的命名空间3.编写使用SQLite代码4.结果展示 0.引言 SQLite是一个轻量级的嵌入式数据库&#xff0c;它的库文件非常小巧&#xff0c;不需要独立的服务器进程或配置。这使得它非常适合在资源受限的环境中使用&#xff…

【Terraform学习】Terraform-AWS部署快速入门(快速入门)

Terraform-AWS部署快速入门 实验步骤 连接到 Terraform 环境 SSH 连接到Terraform 环境(名为MyEC2Instance的实例) 在 Amazon Web Services &#xff08;AWS&#xff09; 上预置 EC2 实例 用于描述 Terraform 中基础结构的文件集称为 Terraform 配置。您将编写一个配置来定义…

防御第三天

1.总结当堂NAT与双机热备原理&#xff0c;形成思维导图 2.完成课堂NAT与双机热备实验 fw1: <USG6000V1>sy [USG6000V1]int g0/0/0 [USG6000V1-GigabitEthernet0/0/0]ip add 192.168.18.2 24 [USG6000V1-GigabitEthernet0/0/0]service-manage all permit (地址无所谓&…

设计模式适合用于解决特定的软件设计问题呢

当我们在开发软件时&#xff0c;经常会遇到各种各样的问题和挑战&#xff0c;例如如何处理对象之间的关系、如何实现复杂的业务逻辑、如何处理并发访问等。这些问题都是软件设计中经常遇到的问题&#xff0c;而设计模式就是为了解决这些问题而诞生的。 以下是一些常见的软件设…

SpringCloud学习路线(11)——分布式搜索ElasticSeach场景使用

一、DSL查询文档 &#xff08;一&#xff09;DSL查询分类 ES提供了基于JSON的DSL来定义查询。 1、常见查询类型&#xff1a; 查询所有&#xff1a; 查询出所有的数据&#xff0c;例如&#xff0c;match_all全文检索&#xff08;full text&#xff09;查询&#xff1a; 利用…

leetcode 50. Pow(x, n)(x的n次方)

求x的n次方。 思路&#xff1a; 第一个想到的思路是x和它自己乘n次&#xff0c; 但是这样做会面临一些问题&#xff1a; 如果是简单的n很小的情况还好&#xff0c;但是可以看到n的取值横跨整个整数范围&#xff0c; 如果n非常大&#xff0c;一次一次乘x效率低是其一。 一般来…

探索网页原型设计:构建出色的用户体验

在当今数字化时代&#xff0c;用户对网页体验的要求日益提高。在网页设计过程中&#xff0c;扮演着至关重要的角色。通过网页原型设计&#xff0c;产品经理能够更好地展示和传达网页的整体布局、导航结构、元素位置和交互效果&#xff0c;从而使团队成员更清晰地了解设计意图&a…

mapboxGL中楼层与室内地图的结合展示

概述 质量不够&#xff0c;数量来凑&#xff0c;没错&#xff0c;本文就是来凑数的。前面的几篇文章实现了楼栋与楼层单体化的展示、室内地图的展示&#xff0c;本文结合前面的几篇文章&#xff0c;做一个综合的展示效果。 实现效果 实现 1. 数据处理 要实现上图所示的效果…

Excel透视表与python实现

目录 一、Excel透视表 1、源数据 2、数据总分析 3、数据top分析 二、python实现 1、第一张表演示 2、第二张表演示 一、Excel透视表 1、源数据 1&#xff09;四个类目&#xff0c;每类50条数据 2&#xff09;数据内容 2、数据总分析 1&#xff09;选择要分析的字段&…

leetcode做题笔记46

给定一个不含重复数字的数组 nums &#xff0c;返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。 思路一&#xff1a;回溯 void swap(int *nums,int index1,int index2) {int temp nums[index1];nums[index1] nums[index2];nums[index2] temp; }void prem(int* nu…

已经重新安装了MySQL,第一次应该如何登录root用户

如果已经重新安装了MySQL&#xff0c;第一次登录root用户需要按照以下步骤进行&#xff1a; 1. 打开命令行终端或控制台。 2. 通过一下命令启动MySQL服务器&#xff1a; sudo systemctl start mysql3. 登录MySQL服务器&#xff1a; sudo mysql -u root 如果服务器在本地主…

vue项目登录页面实现记住用户名和密码

vue项目登录页面实现记住用户名和密码 记录一下实现的逻辑&#xff0c;应该分两步来理解这个逻辑 首次登录&#xff0c;页面没有用户的登录信息&#xff0c;实现逻辑如下&#xff1a; 用户输入用户名和密码登录&#xff0c;用户信息为名为form的响应式对象&#xff0c;v-model…

Linux Day03

一、基础命令(在Linux Day02基础上补充) 1.10 find find 搜索路径 -name 文件名 按文件名字搜索 find 搜索路径 -cmin -n 搜索过去n分钟内修改的文件 find 搜索路径 -ctime -n搜索过去n分钟内修改的文件 1&#xff09;按文件名字 2&#xff09;按时间 1.11 grep 在文件中过…

linux+Jenkins+飞书机器人发送通知(带签名)

文章目录 如何使用在linux 上安装python 环境发送消息python脚本把脚本上传倒linux上 jenkins 上执行脚本 如何使用 自定义机器人使用指南飞书官网https://open.feishu.cn/document/client-docs/bot-v3/add-custom-bot 在linux 上安装python 环境 yum install python3 python…

yolov5检测到的框画到原图上

1.把检测到的框画到原图上 import warnings warnings.filterwarnings(ignore) warnings.simplefilter(ignore) import torch import cv2 import numpy as np import requests import torchvision.transforms as transformsfrom models.common

“深入解析Spring Boot:从入门到进阶“

标题&#xff1a;深入解析Spring Boot&#xff1a;从入门到进阶 摘要&#xff1a;本文将深入解析Spring Boot框架&#xff0c;从入门到进阶&#xff0c;帮助开发者更好地理解和应用Spring Boot。内容包括Spring Boot的基本概念、核心特性、常用组件和高级用法&#xff0c;并提…

如何在3ds max中创建可用于真人场景的巨型机器人:第 5 部分

推荐&#xff1a; NSDT场景编辑器助你快速搭建可二次开发的3D应用场景 1. After Effects 中的项目设置 步骤 1 打开“后效”。 打开后效果 步骤 2 我有真人版 我在After Effects中导入的素材。这是将 用作与机器人动画合成的背景素材。 实景镜头 步骤 3 有背景 选定的素材…