当前位置: 首页 > news >正文

Lua迭代器如何使用?

在Lua中,迭代器是一种用于遍历集合元素的重要工具。掌握迭代器的使用方法,对于提高Lua编程的效率和代码的可读性具有重要意义。

1.迭代器概述

12.1.1 迭代器介绍

迭代器是一种设计模式,它提供了一种访问集合元素的方法,而不需要暴露其底层结构。在Lua中,迭代器通常以一个函数的形式表示,每次调用该函数时,它会返回集合中的下一个元素。当没有更多元素时,迭代器返回nil。

1.2 泛型for循环

在Lua中,泛型for循环用于遍历一个迭代器函数返回的所有值。泛型for循环的基本语法如下: 

for variable1, variable2, ... in iterator_expression do-- 执行代码块
end

这里的iterator_expression通常是一个表达式,它应该返回三个值:迭代器函数、状态变量和初始值。在每一次循环中,Lua会调用迭代器函数,传递状态变量和上一次调用的结果(除了第一次,它会传递初始值)。当迭代器函数返回nil作为第一个值时,循环结束。

1.3 迭代器应用场景

迭代器在Lua中有多种应用场景,例如:

  • 遍历数组或表。
  • 遍历文件中的每一行。
  • 处理数据库查询结果等。

通过使用迭代器,可以更加简洁地处理这些任务,同时保持代码的可读性和可维护性。

2.内置迭代器

Lua提供了两个常用的内置迭代器:

迭代器

作用

pairs(t)

用于遍历表中的所有键值对,它的遍历顺序是不确定的(通常是按照哈希表内部的存储顺序)。

ipairs(t)

用于遍历数组,即从索引1开始直到遇到第一个nil元素为止。它返回两个值:索引和索引对应的元素。

这两个迭代器都是无状态的,意味着它们不保留任何额外的状态信息,只依赖于传递给它们的状态常量和控制变量。

假设有一个包含数字的数组,可以使用ipairs函数来遍历该数组。

-- ipairs_test.lua文件
local numbers = {10, 20, 30}for index, value in ipairs(numbers) doprint(index, value)
end

执行以上脚本代码,程序输出结果如下。

1   10
2   20
3   30

根据上面的示例,下面我们来看看泛型for的执行过程:

  • 首先,初始化,计算in后面表达式的值,表达式应该返回泛型for需要的三个值:迭代函数、状态常量、控制变量;与多值赋值一样,如果表达式返回的结果个数不足三个会自动用nil补足,多出部分会被忽略;
  • 第二,将状态常量和控制变量作为参数调用迭代函数(注意:对于for结构来说,状态常量没有用处,仅仅在初始化时获取它的值并传递给迭代函数);
  • 第三,将迭代函数返回的值赋给变量列表;
  • 第四,如果返回的第一个值为nil循环结束,否则执行循环体;
  • 第五,回到第二步再次调用迭代函数。

对于一个关联数组(哈希表,key-value键值形式),我们可以用pairs来遍历键值对。

-- pairs_test.lua文件
local person = {name = "Alice",age = 30,city = "Beijing"
}for key, value in pairs(person) doprint(key, value)
end

执行以上脚本代码,程序输出结果如下。

name  Alice
age   30
city  Beijing

注意,pairs遍历表元素的顺序不是固定的,如果你想按照特定顺序访问元素,你应该显式地排序或者使用有序的数据结构。

3.自定义迭代器

在Lua编程语言中,迭代器是一种允许程序员遍历数据集合的重要工具。它让开发者可以访问集合中的每一个元素,而无需暴露集合的内部结构。根据是否保存遍历过程的状态,迭代器被分为两种类型:无状态迭代器和多状态迭代器。下面我们将详细介绍这两种迭代器,并提供具体的语法和示例帮助理解。

3.1 无状态迭代器

无状态迭代器是指不保留任何状态信息的迭代器。这意味着,在每次调用迭代函数时,它并不依赖于之前的状态来决定下一个元素的位置。相反,它仅使用两个参数——状态常量(通常是表本身)和控制变量(如索引或键)——来计算并返回下一个元素。例如,ipairs函数就是一个典型的无状态迭代器,它遍历数组的每一个元素,且元素的索引必须是数值。

在Lua中,使用无状态迭代器时,for循环的表达式部分需要提供三个值:

  • 迭代函数:用于生成下一个元素。
  • 状态常量:在迭代过程中不会改变的值,通常是需要遍历的集合。
  • 控制变量:用于控制迭代过程的变量,通常在每次迭代后递增。

无状态迭代器的语法总结一下就是,当使用无状态迭代器时,泛型for循环会保存三个值:迭代函数、状态常量以及控制变量。这些值是在循环开始前由表达式计算出来的。每次迭代时,迭代函数都会以状态常量和控制变量作为参数被调用,并返回新的控制变量和一个或多个元素值。如果返回的第一个非空值为nil,则循环结束。

如下实现了一个简单的数字平方迭代器的例子。

-- no_state_iterator_test.lua文件
function square(iteratorMaxCount, currentNumber)if currentNumber < iteratorMaxCount thencurrentNumber = currentNumber + 1return currentNumber, currentNumber * currentNumberend
endfor i, n in square, 3, 0 doprint(i, n) -- 输出结果为: 1 1, 2 4, 3 9
end

在这个例子中,square函数充当了无状态迭代器的角色。它接收最大计数iteratorMaxCount和当前数字currentNumber作为参数,然后根据这两个值计算出下一个要返回的数字及其平方值。

执行以上脚本代码,程序输出结果如下。

1   1
2   4
3   9

另一个常见的无状态迭代器是ipairs,它是用来遍历数组形式的表的。其工作原理如下所示。

function ipairs(t)return iter, t, 0
endfunction iter(a, i)i = i + 1local v = a[i]if v thenreturn i, vend
end

这段代码展示了如何创建一个类似于ipairs的迭代器,其中iter函数是一个无状态迭代器,因为它只依赖传入的状态常量a和控制变量i来确定下一个元素的位置。

3.2 多状态迭代器

多状态迭代器会在迭代过程中保存额外的状态信息。这使得每个迭代器实例都可以独立地遍历相同的集合,而不会相互影响。为了实现这一点,通常会使用闭包或者将所有必要的状态封装在一个表内,作为迭代器的一部分。

  • 使用闭包:在迭代函数内部定义局部变量来保存状态,这些变量在每次迭代中都会被保留。
  • 使用表:将状态信息封装到一个表中,将表作为迭代器的状态常量传递给迭代函数。

使用闭包。下面是一个创建自定义迭代器的例子,该迭代器可以遍历一个表中的所有元素,同时计算并输出它们的长度。

-- multi_state_iterator_test.lua文件
-- 定义一个数组
local array = {"Google", "Baidu", "ByteDance"}-- 定义一个多状态迭代器
local function elementIterator(collection)local index = 0local count = #collection-- 返回一个闭包作为迭代器return function()index = index + 1if index <= count thenreturn collection[index], string.len(tostring(collection[index]))endend
end-- 使用迭代器遍历数组
for element, length in elementIterator(array) doprint(element, length)
end

在这个例子中,elementIterator函数创建了一个闭包,该闭包维护了一个私有的index计数器和count变量。每当迭代器被调用时,它就会递增index并检查是否超过了count的限制。如果没有超过,则返回当前元素及其字符串表示形式的长度。

执行以上脚本代码,程序输出结果如下。

Google    6
Baidu   5
ByteDance   9

此外,还可以使用表来保存状态信息。例如,如果我们想要遍历一个包含文件路径的表,并读取每个文件的内容,我们可以这样做。

local files = {"file1.txt", "file2.txt"}function fileReader(paths)local i = 0return function()i = i + 1local path = paths[i]if path thenlocal f = io.open(path)if f thenlocal content = f:read("*all")f:close()return path, contentendendend
endfor path, content in fileReader(files) doprint("File:", path)print("Content:", content)
end

这里,fileReader函数创建了一个闭包,该闭包负责打开指定路径下的文件并读取其内容。由于闭包能够捕获并记住外部作用域中的变量,因此它可以轻松地跟踪正在处理的是哪个文件。

最后对无状态迭代器和多状态迭代器做如下总结:

  • 无状态迭代器:不保留任何状态,每次迭代都只依赖于迭代函数、状态常量和控制变量。适用于简单的迭代场景,如遍历数组。
  • 多状态迭代器:需要保存多个状态信息,可以通过闭包或表来实现。适用于复杂的迭代场景,如遍历文件中的单词。

综上所述,无论是无状态还是多状态迭代器,它们都提供了灵活且强大的机制来遍历各种类型的集合。选择哪种迭代器取决于具体的应用场景和个人偏好。

相关文章:

Lua迭代器如何使用?

在Lua中&#xff0c;迭代器是一种用于遍历集合元素的重要工具。掌握迭代器的使用方法&#xff0c;对于提高Lua编程的效率和代码的可读性具有重要意义。 1.迭代器概述 12.1.1 迭代器介绍 迭代器是一种设计模式&#xff0c;它提供了一种访问集合元素的方法&#xff0c;而不需要…...

qt中如何判断字符串是否为数字,整数,浮点数?

在 Qt 中&#xff0c;可以使用多种方法来判断字符串是否为数字、整数或浮点数。Qt 提供了一些方便的字符串和数值处理函数&#xff0c;可以帮助你实现这些判断。以下是几种常见的方法&#xff1a; 1. 使用 QRegularExpression Qt 提供了 QRegularExpression 类&#xff0c;可…...

Oracle sql developer and Toad for Oracle set start DBMS output

Oracle sql developer Toad for Oracle...

【踩坑】SparkSQL union/unionAll 函数的去重问题

【踩坑】SparkSQL union/unionAll 函数的去重问题 测试数据 case class Employee(first_name:String)val employeeDF1 spark.createDataset(Seq( Employee("Mary"), Employee("Mandy"),Employee("Kurt") )) val employeeDF2 spark.createDat…...

域上的多项式环,整除,相通,互质

例1.已知 (R,,x)为域&#xff0c;请选出正确的说法:(A)(R,,x)也是整区; ABCD (B)R中无零因子; C)R在x运算上满足第一、二、三指数律; (D)R只有平凡理想; (E)R只有平凡子环。 域的特征&#xff1a; 域中&#xff0c;非0元素的加法周期 思考、在模7整数环R,中&#xff0c;…...

计算机毕业设计PyHive+Hadoop深圳共享单车预测系统 共享单车数据分析可视化大屏 共享单车爬虫 共享单车数据仓库 机器学习 深度学习

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Julia语言的学习路线

Julia语言的学习路线 引言 在现代编程世界中&#xff0c;编程语言如同工具&#xff0c;各自具有独特的特点与优势。Julia语言自2012年发布以来&#xff0c;以其优越的性能和优雅的语法逐渐吸引了越来越多的数据科学家、工程师和研究人员的关注。在本篇文章中&#xff0c;我们…...

对计网大题的一些指正(中间介绍一下CDM的原理和应用)

目录 前言&#xff1a; &#xff08;1&#xff09;五层原理体系结构每层功能&#xff1a; 下面是文档的答案&#xff1a; 我在之前的博客里面有介绍过五层原理体系结构&#xff0c; 按理来说&#xff0c;第五层应该是应用层才对&#xff0c;而会话层的功能应该被放到应用层…...

UGUI 优化DrawCall操作记录(基于Unity2021.3.18)

UGUI中相同材质相同Shader相同贴图的UI元素可以合并DrawCall。 1.使用图集 Unity性能优化---使用SpriteAtlas创建图集进行批次优化_unity2021.3.33 spriteatlas优化-CSDN博客 2.Canvas的子物体在场景树中的索引位置和不同图集不影响UI合批且UI网格没有重叠&#xff0c;如下图…...

前端实现大文件上传(文件分片、文件hash、并发上传、断点续传、进度监控和错误处理,含nodejs)

大文件分片上传是前端一种常见的技术&#xff0c;用于提高大文件上传的效率和可靠性。主要原理和步骤如下 文件分片 确定分片大小&#xff1a;确定合适的分片大小。通常分片大小在 1MB 到 5MB 之间使用 Blob.slice 方法&#xff1a;将文件分割成多个分片。每个分片可以使用 Bl…...

es单机安装脚本自动化

背景 所有部署工作都可以由机器本身完成,并不需要人的参与,人唯一需要做的是把变量提取出来,进行赋值喂给脚本,然后脚本自己执行即可。下边是es单机安装的过程和脚本,由人变到脚本执行,方便理解。 步骤 1、解压es软件tar包。 2、cd至解压以后得config目录下,vim修改…...

Java 数据库连接 - Sqlite

Java 数据库连接 - Sqlite PS: 1. 连接依赖库&#xff1a;[sqlite-jdbc-xxx.jar](https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc)(根据连接的数据库版本选择) 2. 支持一次连接执行多次sql语句&#xff1b; 3. 仅本地连接&#xff1b;使用说明&#xff1a; publ…...

CentOS — 目录管理

文章目录 一、目录结构二、切换目录三、查看目录四、创建目录五、复制目录六、剪切目录七、删除目录 目录也是一种文件。 蓝色目录&#xff0c;绿色可执行文件&#xff0c;红色压缩文件&#xff0c;浅蓝色链接文件&#xff0c;灰色其它文件&#xff0c; 点开头的是隐藏文件&…...

【第二部分--Python之基础】04 函数

1 定义函数 自定义函数的语法格式如下&#xff1a; 以英文半角冒号结尾 由于定义函数时的参数不是实际数据&#xff0c;会在调用函数时传递给它们实际数据&#xff0c;所以我们称定义函数时的参数为形式参数&#xff0c;简称形参:称调用函数时传递的实际数据为实际参数&#x…...

我们公司只有3个人,一个前端,一个后端

在当今这个数字化时代&#xff0c;各行各业都离不开互联网技术的支撑&#xff0c;而在这股技术浪潮中&#xff0c;小而美的创业公司如同雨后春笋般涌现&#xff0c;它们凭借着灵活高效、创新不断的特点&#xff0c;在市场中占有一席之地。 今天&#xff0c;就让我带你走进这样一…...

基于LabVIEW的BeamGage自动化接口应用

设置 National Instruments LabVIEW可执行程序需要被配置为使用.NET 4框架。.NET允许自定义可执行程序的运行方式。可通过以下方式实现&#xff1a; 在LabVIEW安装目录中创建一个名为LabVIEW.exe.config的文本文件&#xff08;例如&#xff1a;C:\Program Files\National Ins…...

【AI编辑器】Cursor与DeepSeek模型的集成:提升开发效率的新选择

目录 一、为什么选择DeepSeek模型 1.1 模型参数与训练 1.2 技术创新 1、FP8格式介绍 2、FP8混合精度训练的优势 3、FP8混合精度训练的技术要点 4、FP8混合精度训练的应用与挑战 1.3 性能表现 1.4 应用与部署 1.5 争议与前景 二、注册DeepSeek账号并获取API Key 三、…...

vue2实现excel文件预览

一、插件 通过xlsx插件解析excel数据&#xff0c;对解析后的html组件进行渲染展示。 npm install xlsx 二、完整代码 <template><!-- excel文件预览 --><divelement-loading-text"拼命加载中"element-loading-spinner"el-icon-loading"…...

STM32 和 ESP32

STM32 和 ESP32 是两种不同的微控制器系列&#xff0c;它们分别由不同的制造商生产&#xff0c;并且针对的应用场景和特性也有所不同。尽管如此&#xff0c;两者也有一些共通点&#xff0c;因为它们都是用于嵌入式系统开发的微控制器平台。以下是关于 STM32 和 ESP32 的联系与区…...

R语言中的时间序列分析·

1 数据集说明 AirPassengers 1949~1960年每月乘坐飞机的乘客数 JohnsonJohnson Johnson&Johnson每股季度收入 nhtemp 康涅狄格州纽黑文地区从1912年至1971年每年的平均气温 Nile 尼罗河的流量 sunspots 1749年~1983年月平均太阳黑子数 2 相关包 xts、forecast、tser…...

QML学习(六) anchors锚点和坐标,以及anchors锚点的使用

先来看看上一篇文章中的代码和效果 上一篇中讲到&#xff0c;第一个QML程序虽然做出来了&#xff0c;但程序界面里边元素的显示位置跟预想的不一样&#xff0c;这其实就是整体上对QML中的坐标使用存在问题。 改成这样&#xff0c;全以锚点来控制各个元素的坐标 import QtQuic…...

BFS广度优先搜索详解

对于BFS的&#xff0c;我来谈一谈自己的理解。首先&#xff0c;我们从一道最基础的题来进行学习: 洛谷B3625 迷宫寻路&#xff08;仔细阅读哦&#xff0c;我就不解释了&#xff09; B3625 迷宫寻路 - 洛谷 | 计算机科学教育新生态 对于这道题以及所有的BFS题目的核心&#x…...

vue项目利用webpack进行优化案例

使用 Webpack 优化 Vue 项目是提升性能和减少打包体积的关键步骤。以下是几个常见的优化案例及其详细实现方法&#xff1a; 1. 优化打包大小 1.1 按需加载 (Lazy Loading) Vue 提供了路由懒加载功能&#xff0c;可以将组件拆分成独立的块&#xff0c;按需加载&#xff0c;从而…...

如何单独安装 MATLAB 工具箱

很多时候由于 MATLAB 太大而选择安装一些 Toolbox&#xff0c;但用着用着发现要用到某个没有安装的 Toolbox&#xff0c;这时候就需要再单独安装这个 Toolbox&#xff0c;下面提供两种方法。 本文以安装 系统辨识工具箱 System Identification Toolbox 为例。 方法一&#xf…...

组网实训实现

小型单元网络实现 IP划分&#xff1a; 外网:172.1.1.0/24 172.1.2.0/24 内网&#xff1a;基于192.168.3.0/24的子网划分 综合办公楼&#xff1a;192.168.3.00 000000 /26&#xff08;192.168.3.0-192.168.3.63&#xff09; 综合一楼&#xff1a;192.168.3.0000 0000 /28&…...

openbmc sdk09.03 适配(一)

1.说明 本节是根据最新的sdk09.03适配ast2600平台。 sdk下载路径为: https://github.com/AspeedTech-BMC/openbmc可参阅文档: https://blog.csdn.net/wit_yuan/article/details/144613247nfs挂载方法: # mount -o nolock -t nfs serverip:/xx...

SQL使用存储过程

本文介绍什么是存储过程&#xff0c;为什么要使用存储过程&#xff0c;如何使用存储过程&#xff0c;以及创建和使用存储过程的基本语法。 1. 存储过程 迄今为止&#xff0c;我们使用的大多数SQL语句都是针对一个或多个表的单条语句。并非所有操作都这么简单&#xff0c;经常…...

C语言----函数、指针、数组

目录 ​编辑 指针函数 本质 格式&#xff1a; 函数指针 1、 概念 2、 格式 3、 举例 3.1基本用法 3.2函数指针作为函数参数的用法(回调函数) 函数指针数组 1. 概念 2. 格式 3. 例子 指针函数 本质 是函数&#xff0c;返回值为指针 格式&#xff1a; 数据类型…...

基于Java的敬老院管理系统的设计和实现【源码+文档+部署讲解】

基于Java的敬老院管理系统设计和实现 摘 要 新世纪以来,互联网与计算机技术的快速发展,我国也迈进网络化、集成化的信息大数据时代。对于大众而言,单机应用早已成为过去&#xff0c;传统模式早已满足不了当下办公生活等多种领域的需求,在一台电脑上不联网的软件少之又少&#x…...

12306分流抢票软件 bypass v1.16.43 绿色版(春节自动抢票工具)

软件介绍 12306Bypass分流抢票软件&#xff0c;易操作强大的12306抢票软件&#xff0c;全程自动抢票&#xff0c;云识别验证码打码&#xff0c;多线程秒单、稳定捡漏&#xff0c;支持抢候补票、抢到票自动付款&#xff0c;支持多天、多车次、多席别、多乘客、短信提醒等功能。…...