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) do
  print(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) do
  print(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 then
    currentNumber = currentNumber + 1
    return currentNumber, currentNumber * currentNumber
  end
end

for i, n in square, 3, 0 do
  print(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
end

function iter(a, i)
  i = i + 1
  local v = a[i]
  if v then
    return i, v
  end
end

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

3.2 多状态迭代器

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

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

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

-- multi_state_iterator_test.lua文件
-- 定义一个数组
local array = {"Google", "Baidu", "ByteDance"}

-- 定义一个多状态迭代器
local function elementIterator(collection)
  local index = 0
  local count = #collection
  -- 返回一个闭包作为迭代器
  return function()
    index = index + 1
    if index <= count then
      return collection[index], string.len(tostring(collection[index]))
    end
  end
end

-- 使用迭代器遍历数组
for element, length in elementIterator(array) do
  print(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 = 0
  return function()
    i = i + 1
    local path = paths[i]
    if path then
      local f = io.open(path)
      if f then
        local content = f:read("*all")
        f:close()
        return path, content
      end
    end
  end
end

for path, content in fileReader(files) do
  print("File:", path)
  print("Content:", content)
end

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

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

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA-制作小游戏期末实训

源码 import game.frame.Frame;public class App {public static void main(String[] args) {System.out.println("starting......");new Frame();} } package game.controller;import game.model.Enemy;public class EnemyController implements Runnable{private…

Linux Red Hat 7.9 Server安装GitLab

1、关闭防火墙 执行 systemctl disable firewalld 查看服务器状态 systemctl status firewalld 2、禁用selinux vi /etc/selinux/config 将SELINUX 的值改为 disabled 3、安装policycoreutils-python 执行 yum install policycoreutils-python 4、下载gitlab wget --co…

Windows 环境配置 HTTPS 服务实战

一、 环境准备 win10以上操作系统安装 Certbot申请阿里云\腾讯云域名安装 nginx 1.3以上版本 二、Certbot 安装及 SSL 证书生成 Certbot 是一个免费、开源工具&#xff0c;用于自动化在Web服务器上获取和更新SSL/TLS证书。它可以通过Let’s Encrypt服务获取免费的SSL/TLS证书…

普及组集训数据结构--并查集

P1551 亲戚 - 洛谷 | 计算机科学教育新生态 并查集就是把所有相关联的量串成一串珠子&#xff0c;抽象来说就是&#xff1a; 把此类相关联的量当作节点&#xff0c;两个节点之间连接一条无向边&#xff0c;所形成的图 例题算法流程&#xff1a; 在此定义“族长”就是一个树的…

windows编译llama.cpp GPU版本

Build 指南 https://github.com/ggerganov/llama.cpp/blob/master/docs/build.md 一、Prerequire 具体步骤&#xff08;以及遇到的坑&#xff09;&#xff1a; 如果你要使用CUDA&#xff0c;请确保已安装。 1.安装 最新的 cmake, git, anaconda&#xff0c; pip 配置pyt…

Android 性能优化:内存优化(实践篇)

1. 前言 前一篇文章Android性能优化&#xff1a;内存优化 &#xff08;思路篇&#xff09; 大概梳理了Android 内存原理和优化的必要性及应该如何优化&#xff0c;输出了一套短期和长期内存优化治理的SOP方案。 那么这一篇文章就总结下我最近在做内存优化如何实践的&#xff0…

「Mac畅玩鸿蒙与硬件53」UI互动应用篇30 - 打卡提醒小应用

本篇教程将实现一个打卡提醒小应用&#xff0c;通过用户输入时间进行提醒设置&#xff0c;并展示实时提醒状态&#xff0c;实现提醒设置和取消等功能。 关键词 打卡提醒状态管理定时任务输入校验UI交互 一、功能说明 打卡提醒小应用包含以下功能&#xff1a; 提醒时间输入与…

Nginx知识详解(理论+实战更易懂)

目录 一、Nginx架构和安装 1.1 Nginx 概述 1.1.1 nginx介绍 1.1.2?Nginx 功能介绍 1.1.3?基础特性 1.1.4?Web 服务相关的功能 1.2?Nginx 架构和进程 1.2.1?Nginx 进程结构 1.2.2?Nginx 进程间通信 1.2.3?Nginx 启动和 HTTP 连接建立 1.2.4?HTTP 处理过程 1…

Postgresql 命令还原数据库

因为PgAdmin打不开&#xff0c;但是数据库已经安装成功了&#xff0c;这里借助Pg命令来还原数据库 C:\Program Files\PostgreSQL\15\bin\psql.exe #链接数据库 psql -U postgres -p 5432#创建数据库 CREATE DATABASE "数据库名称"WITHOWNER postgresENCODING UTF8…

Vue 解决浏览器刷新路由参数丢失问题 全局统一配置无需修改组件

在路由跳转的时候,我们经常会传一些参数过去,然后通过传过来的参数调用接口获取相关数据,但是刷新浏览器的时候路由参数会丢失。此时页面报错误了,如何通过全局配置的方式,不需要修改任何组件 实现刷新浏览器保存参数? 实现方式如下: 首先在router/index.js里添加参数管…

【AIGC】电话录音转文字实践:基于Google Cloud Speech-to-Text-v1的技术方案Python

文章目录 引言技术原理技术方案设计系统架构关键技术要点 代码实现1. 环境准备2. 核心代码实现3. 音频预处理工具响应格式 性能优化实践经验应用场景未来展望总结 引言 在当今数字化时代&#xff0c;将语音内容转换为文字已经成为一个非常重要的技术需求。无论是客服通话记录、…

RabbitMQ-基本使用

RabbitMQ: One broker to queue them all | RabbitMQ 官方 安装到Docker中 docker run \-e RABBITMQ_DEFAULT_USERrabbit \-e RABBITMQ_DEFAULT_PASSrabbit \-v mq-plugins:/plugins \--name mq \--hostname mq \-p 15672:15672 \-p 5672:5672 \--network mynet\-d \rabbitmq:3…

Android Camera压力测试工具

背景描述&#xff1a; 随着系统的复杂化和业务的积累&#xff0c;日常的功能性测试已不足以满足我们对Android Camera相机系统的测试需求。为了确保Android Camera系统在高负载和多任务情况下的稳定性和性能优化&#xff0c;需要对Android Camera应用进行全面的压测。 对于压…

vscode中调用deepseek实现AI辅助编程

来自 Python大数据分析 费弗里 1 简介 大家好我是费老师&#xff0c;最近国产大模型Deepseek v3新版本凭借其优秀的模型推理能力&#xff0c;讨论度非常之高&#x1f525;&#xff0c;且其官网提供的相关大模型API接口服务价格一直走的“价格屠夫”路线&#xff0c;性价比很高…

基于 LMS 算法的离散傅里叶分析器

基于 LMS&#xff08;Least Mean Squares&#xff0c;最小均方&#xff09;算法的离散傅里叶分析器是一种结合自适应滤波和频域分析的工具&#xff0c;用于动态估计信号的频谱成分。它将 LMS 自适应算法与离散傅里叶变换&#xff08;DFT&#xff09;的频率分解能力结合&#xf…

2022浙江大学信号与系统笔记

原视频地址&#xff1a;2022浙江大学信号与系统&#xff08;含配套课件和代码&#xff09; - 胡浩基老师-哔哩哔哩 ⭐⭐⭐ 我的笔记&#xff1a;飞书链接 - 信号与系统 基于视频&#xff0c;记得笔记&#xff0c;加了点自己的补充&#xff08;有的是问 ChatGPT 的&#xff09;…

K8s高可用集群之Kubernetes集群管理平台、命令补全工具、资源监控工具部署、常用命令

K8s高可用集群之Kubernetes管理平台、补全命令工具、资源监控工具部署 1.Kuboard可视化管理平台2.kubectl命令tab补全工具3.MetricsServer资源监控工具4.Kubernetes常用命令 1.Kuboard可视化管理平台 可以选择安装k8s官网的管理平台&#xff1b;我这里是安装的其他开源平台Kub…

Gitlab-runner 修改默认的builds_dir并使用custom_build_dir配置

gitlab-runner 修改默认的builds_dir并使用custom_build_dir配置 1. 说明2. 实操&#xff08;以docker执行器为例&#xff09;2.1 修改默认的builds_dir2.1.1 调整gitlab-runner的配置文件2.1.2 CI文件 2.2 启用custom_build_dir2.2.1 调整gitlab-runner的配置文件2.2.2 CI文件…

网络IP协议

IP&#xff08;Internet Protocol&#xff0c;网际协议&#xff09;是TCP/IP协议族中重要的协议&#xff0c;主要负责将数据包发送给目标主机。IP相当于OSI&#xff08;图1&#xff09;的第三层网络层。网络层的主要作用是失陷终端节点之间的通信。这种终端节点之间的通信也叫点…

SpringCloud源码-Ribbon

一、Spring定制化RestTemplate&#xff0c;预留出RestTemplate定制化扩展点 org.springframework.cloud.client.loadbalancer.LoadBalancerAutoConfiguration 二、Ribbon定义RestTemplate Ribbon扩展点功能 org.springframework.cloud.netflix.ribbon.RibbonAutoConfiguratio…