【Lua从青铜到王者基础篇】第七篇:Lua数组和迭代器

x33g5p2x  于2022-03-11 转载在 其他  
字(5.2k)|赞(0)|评价(0)|浏览(252)

系列文章目录

前言

🌲一、Lua数组

数组,就是相同数据类型的元素按一定顺序排列的集合,可以是一维数组和多维数组。

Lua 数组的索引键值可以使用整数表示,数组的大小不是固定的。

🌲1.一维数组

一维数组是最简单的数组,其逻辑结构是线性表。一维数组可以用for循环出数组中的元素,如下实例:

print("--------------------数组-------------------")

print("--------------------一维数组---------------")
array1={"Lua","Tutorial"}

for i=0,3 
do
   print(array1[i])
end

for i=1,2 
do
   print(array1[i])
end

以上代码的输出结果为:

--------------------数组-------------------
Untitled-1.lua:730
--------------------一维数组---------------
Untitled-1.lua:732
nil
Untitled-1.lua:737
Lua
Untitled-1.lua:737
Tutorial
Untitled-1.lua:737
nil
Untitled-1.lua:737
Lua
Untitled-1.lua:742
Tutorial

  • 正如你所看到的,我们可以使用整数索引来访问数组元素,如果知道的索引没有值则返回nil。
  • 在 Lua 索引值是以 1 为起始,但你也可以指定 0 开始。
  • 除此外我们还可以以负数为数组索引值:
for i=1,2 
do
   print(array1[i])
end

array2={};
for i=-2,2 
do
   array2[i]=i*2
end

for i=-2,2
do
   print(array2[i])
end

以上代码的输出结果为:

-4
Untitled-1.lua:753
-2
Untitled-1.lua:753
0
Untitled-1.lua:753
2
Untitled-1.lua:753
4

🌳2.多维数组

多维数组即数组中包含数组或一维数组的索引键对应一个数组。

以下是一个三行三列的阵列多维数组:

print("------------------------多维数组------------------")

array3={}
for i=1,3
do
   array3[i]={}
   for j=1,3
   do
      array3[i][j]=i*j
   end
end

print("------------------------访问数组------------------")
for i=1,3
do
   for j=1,3
   do
      print(array3[i][j])
   end
end

以上代码的输出结果为:

------------------------多维数组------------------
Untitled-1.lua:757
------------------------访问数组------------------
Untitled-1.lua:769
1
Untitled-1.lua:774
2
Untitled-1.lua:774
3
Untitled-1.lua:774
2
Untitled-1.lua:774
4
Untitled-1.lua:774
6
Untitled-1.lua:774
3
Untitled-1.lua:774
6
Untitled-1.lua:774
9

不用的索引键三行三列数组

array4={}
maxRows=3
maxColumns=3
for rows=1,maxColumns
do
   for cols=1,maxColumns
   do
       array4[rows*maxColumns+cols]=rows*cols
   end
end

print("------------------------访问数组------------------")
for rows=1,maxRows
do
   for cols=1,maxColumns
   do
   print(array4[rows*maxColumns+cols])
   end
end

--以上的实例中,数组设定了指定的索引值,这样可以避免出现 nil 值,有利于节省内存空间。

以上代码的输出结果为:

------------------------访问数组------------------
Untitled-1.lua:791
1
Untitled-1.lua:796
2
Untitled-1.lua:796
3
Untitled-1.lua:796
2
Untitled-1.lua:796
4
Untitled-1.lua:796
6
Untitled-1.lua:796
3
Untitled-1.lua:796
6
Untitled-1.lua:796
9

以上的实例中,数组设定了指定的索引值,这样可以避免出现 nil 值,有利于节省内存空间。

🌳二、Lua迭代器

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。

在 Lua 中迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素。

🌲1.泛型for的迭代器

  • 泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数、状态常量、控制变量。
  • 泛型 for 迭代器提供了集合的 key/value 对,语法格式如下:
for k, v in pairs(t) do
    print(k, v)
end

上面代码中,k, v为变量列表;pairs(t)为表达式列表。

查看以下实例:

print("-----------------迭代器-------------")

---语法  key,value键值模型,pairs和inpairs的区别,pairs 和 ipairs区别:table和数组的区别 ,返回nil时候的区别
 --pairs: 迭代 table,可以遍历表中所有的 key 可以返回 nil   
 --ipairs: 迭代数组,不能返回 nil,如果遇到 nil 则退出
s={1,2}
for k,v in pairs(s)
do 
   print(k,v)
end

array5={"Hello","world"}

for key,value in ipairs(array5)
do
   print(key,value)
end

以上代码的输出结果为:

-----------------迭代器-------------
Untitled-1.lua:804
1	1
Untitled-1.lua:812
2	2
Untitled-1.lua:812
1	Hello
Untitled-1.lua:819
2	world

以上实例中我们使用了 Lua 默认提供的迭代函数 ipairs。

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

在Lua中我们常常使用函数来描述迭代器,每次调用该函数就返回集合的下一个元素。Lua 的迭代器包含以下两种类型:

  • 无状态的迭代器。
  • 多状态的迭代器。

🌳2.无状态的迭代器

  • 无状态的迭代器是指不保留任何状态的迭代器,因此在循环中我们可以利用无状态迭代器避免创建闭包花费额外的代价。
  • 每一次迭代,迭代函数都是用两个变量(状态常量和控制变量)的值作为参数被调用,一个无状态的迭代器只利用这两个值可以获取下一个元素。
  • 这种无状态迭代器的典型的简单的例子是 ipairs,它遍历数组的每一个元素,元素的索引需要是数值。

以下实例我们使用了一个简单的函数来实现迭代器,实现 数字 n 的平方:

-----无状态的迭代器是指不保留任何状态的迭代器,因此在循环中我们无可以利用无状态迭代器避免创建闭包花费额外的代价。
-----每一次迭代,迭代函数都是用两个变量(状态常量和控制变量)的值作为参数被调用,一个无状态的迭代器只利用这两个值可以获取下一个元素。
-----这种无状态迭代器的典型的简单的例子是 ipairs,它遍历数组的每一个元素,元素的索引需要是数值。

-----以下实例我们使用了一个简单的函数来实现迭代器,实现 数字 n 的平方:

-----0<3
-----0+1
-----1,1*1
-----返回1
-----1<3
-----1+1
-----2,2*2
-----返回4
-----2<3
-----2+1
-----3,3*3
-----返回9

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)
end
-----无状态的迭代器是指不保留任何状态的迭代器,因此在循环中我们无可以利用无状态迭代器避免创建闭包花费额外的代价

以上代码的输出结果为:

1	1
Untitled-1.lua:852
2	4
Untitled-1.lua:852
3	9

迭代的状态包括被遍历的表(循环过程中不会改变的状态常量)和当前的索引下标(控制变量),ipairs 和迭代函数都很简单,我们在 Lua 中可以这样实现:

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

function ipairs(a)
   return iter,a,0
end
  • 当 Lua 调用 ipairs(a) 开始循环时,他获取三个值:迭代函数 iter、状态常量 a、控制变量初始值 0;然后 Lua 调用 iter(a,0) 返回 1, a[1](除非 a[1]=nil)。
  • 第二次迭代调用 iter(a,1) 返回 2, a[2]……直到第一个 nil 元素。

🌴3.多状态的迭代器

很多情况下,迭代器需要保存多个状态信息而不是简单的状态常量和控制变量**,最简单的方法是使用闭包,还有一种方法就是将所有的状态信息封装到 table 内,将 table 作为迭代器的状态常量,因为这种情况下可以将所有的信息存放在 table 内,所以迭代函数通常不需要第二个参数。**

以下实例我们创建了自己的迭代器:

print("-----------------多状态迭代器-------------")

array6={"hello","world","Lua","language"}    

function elementIterator (collection)              --不止有两个变量时候--状态常量和控制变量那么就使用闭包函数
   local index=0
   local count=#collection
   --闭包函数
   return function()
      index=index+1
      if index <= count
      then
         --返回迭代器的当前元素
         return collection[index]
      end
   end
end

for element in elementIterator(array6)
do
   print(element)
end

--以上实例中我们可以看到,elementIterator 内使用了闭包函数,实现计算集合大小并输出各个元素。

以上代码的输出结果为:

在这里插入代码片
-----------------多状态迭代器-------------
Untitled-1.lua:884
hello
Untitled-1.lua:904
world
Untitled-1.lua:904
Lua
Untitled-1.lua:904
language

以上实例中我们可以看到,elementIterator 内使用了闭包函数,实现计算集合大小并输出各个元素。

💬🌲🌳🌴🌵总结

以上就是今天要讲的内容,本文介绍了Lua数组和Lua迭代器的使用,而数组和迭代器相关操作提供了大量能使我们快速便捷地处理数据的函数和方法,我们务必掌握。另外如果上述有任何问题,请懂哥指教,不过没关系,主要是自己能坚持,更希望有一起学习的同学可以帮我指正,但是如果可以请温柔一点跟我讲,爱与和平是永远的主题,爱各位了。

相关文章