美文网首页
3、表的遍历?

3、表的遍历?

作者: GameObjectLgy | 来源:发表于2020-10-20 01:12 被阅读0次
四种方式遍历table
  • for泛型遍历:pairs
    for key, value in pairs(tbtest) do
    XXX
    end
  • for泛型遍历:ipairs
    for key, value in ipairs(tbtest) do
    XXX
    end

  • for数值遍历 #(tbtest)
    for i=1, #(tbtest) do
    XXX
    end

  • for数值 table.maxn(tbtest)
    for i=1, table.maxn(tbtest) do
    XXX
    end

首先要明确一点,就是lua中table并非像是C/C++中的数组一样是顺序存储的,准确来说lua中的table更加像是C++中的map,通过Key对应存储Value,但是并非顺序来保存key-value对,而是使用了hash的方式,这样能够更加快速的访问key对应的value,我们也知道hash表的遍历需要使用所谓的迭代器来进行,同样,lua也有自己的迭代器,pairs和ipairs遍历就是使用迭代器遍历。

tbtest = {
[1] = 1,
[2] = 2,
[3] = 3,
[4] = 4,
}

for key, value in pairs(tbtest) do
print(value)
end
我认为输出应该是1,2,3,4,实际上的输出是1,2,4,3。我因为这个造成了一个bug,这是后话。
也就是说for k,v in pairs(tbtest) do 这样的遍历顺序并非是tbtest中table的排列顺序,而是根据tbtest中key的hash值排列的顺序来遍历的。

当然,同时lua也提供了按照key的大小顺序来遍历的,注意,是大小顺序,仍然不是key定义的顺序,这种遍历方式就是for k,v in ipairs(tbtest) do。

for k,v in ipairs(tbtest) do 这样的循环必须要求tbtest中的key为顺序的,而且必须是从1开始,ipairs只会从1开始按连续的key顺序遍历到key不连续为止。

tbtest = {
[1] = 1,
[2] = 2,
[3] = 3,
[5] = 5,
}

for k,v in ipairs(tbtest) do
print(v)
end

只会打印1,2,3。而5则不会显示。

local tbtest = {
[2] = 2,
[3] = 3,
[5] = 5,
}

for k,v in ipairs(tbtest) do
print(v)
end
这样就一个都不会打印。

第三种遍历方式有一种神奇的符号'#',这个符号的作用是是获取table的长度,比如:

tbtest = {
[1] = 1,
[2] = 2,
[3] = 3,
}
print(#(tbtest))
打印的就是3

tbtest = {
[1] = 1,
[2] = 2,
[6] = 6,
}
print(#(tbtest))
这样打印的就是2,而且和table内的定义顺序没有关系,无论你是否先定义的key为6的值,‘#’都会查找key为1的值开始。

如果table的定义是这样的:

tbtest = {
["a"] = 1,
[2] = 2,
[3] = 3,
}

print(#(tbtest))
那么打印的就是0了。因为‘#’没有找到key为1的值。

同样:
tbtest = {
[“a”] = 1,
[“b”] = 2,
[“c”] = 3,
}
print(#(tbtest))
打印的也是0

所以,for i=1, #(tbtest) do这种遍历,只能遍历当tbtest中存在key为1的value时才会出现结果,而且是按照key从1开始依次递增1的顺序来遍历,找到一个递增不是1的时候就结束不再遍历,无论后面是否仍然是顺序的key,比如:

table.maxn获取的只针对整数的key,字符串的key是没办法获取到的,比如:

tbtest = {
[1] = 1,
[2] = 2,
[3] = 3,
}
print(table.maxn(tbtest))

tbtest = {
[6] = 6,
[1] = 1,
[2] = 2,
}
print(table.maxn(tbtest))
这样打印的就是3和6,而且和table内的定义顺序没有关系,无论你是否先定义的key为6的值,table.maxn都会获取整数型key中的最大值。
如果table的定义是这样的:

tbtest = {
["a"] = 1,
[2] = 2,
[3] = 3,
}
print(table.maxn(tbtest))
那么打印的就是3了。如果table是:

tbtest = {
[“a”] = 1,
[“b”] = 2,
[“c”] = 3,
}
print(table.maxn(tbtest))
print(#(tbtest))
那么打印的就全部是0了。

换句话说,事实上因为lua中table的构造表达式非常灵活,在同一个table中,你可以随意定义各种你想要的内容,比如:

tbtest = {
[1] = 1,
[2] = 2,
[3] = 3,
["a"] = 4,
["b"] = 5,
}
同时由于这个灵活性,你也没有办法获取整个table的长度,其实在coding的过程中,你会发现,你真正想要获取整个table长度的地方几乎没有,你总能采取一种非常巧妙的定义方式,把这种需要获取整个table长度的操作避免掉,比如:

tbtest = {
tbaaa = {
[1] = 1,
[2] = 2,
[3] = 3,
},
["a"] = 4,
["b"] = 5,
}
你可能会惊讶,上面这种table该如何遍历呢?

for k, v in pairs(tbtest) do
print(k, v)
end
输出是:a 4 b 5 tbaaa table:XXXXX。

由此你可以看到,其实在table中定义一个table,这个table的名字就是key,对应的内容其实是table的地址。
当然,如果你用

for k, v in ipairs(tbtest) do
print(k,v)
end
来遍历的话,就什么都不会打印,因为没有key为1的值。但当你增加一个key为1的值时,ipairs只会打印那一个值,现在你明白ipairs是如何工作的吧。
for i=1, #tbtest do --这种方式无法遍历所有的元素,因为'#'只会获取tbtest中从key为1开始的key连续的那几个元素,如果没有key为1,那么这个循环将无法进入

for i=1, table.maxn(tbtest) do --这种方式同样无法遍历所有的元素,因为table.maxn只会获取key为整数中最大的那个数,遍历的元素其实是查找tbtest[1]~tbtest[整数key中最大值],所以,对于string做key的元素不会去查找,而且这么查找的效率低下,因为如果你整数key中定义的最大的key是10000,然而10000以下的key没有几个,那么这么遍历会浪费很多时间,因为会从1开始直到10000每一个元素都会查找一遍,实际上大多数元素都是不存在的。

for k, v in pairs(tbtest) do
这个是唯一一种可以保证遍历tbtest中每一个元素的方式,别高兴的太早,这种遍历也有它自身的缺点,就是遍历的顺序不是按照tbtest定义的顺序来遍历的,这个前面讲到过,当然,对于不需要顺序遍历的用法,这个是唯一可靠的遍历方式。

for k, v in ipairs(tbtest) do
这个只会遍历tbtest中key为整数,而且必须从1开始的那些连续元素,如果没有1开始的key,那么这个遍历是无效的

相关文章

  • 3、表的遍历?

    四种方式遍历table for泛型遍历:pairsfor key, value in pairs(tbtest) ...

  • 1、邻接矩阵 2、邻接表 3、广度优先遍历 4、深度优先遍历①递归 ②非递归 Dijkstra算法 Floyd-W...

  • 算法

    01 顺序表API设计 顺序表遍历 顺序表容量可变 02 单向链表API设计 遍历 03 双向链表API设计 04...

  • 二叉树遍历-非递归方式

    初始化代码 用链式线性表做栈 先序遍历 中序遍历 后序遍历 输出结果

  • js如何遍历map类型

    1、forEach遍历: 2、for-of遍历: 3、entries遍历:

  • 数据结构——图

    目录 1、相关术语 2、图的表示 2.1、邻接矩阵 2.2、邻接表 3、图的遍历 3.1、深度优先搜索 3.2、广...

  • 从0开始——图

    1图的概念 2.图的存储结构 1.邻接矩阵 2.邻接表 3.图的遍历 1.2邻接表的深度优先算法 1.3扩展:马踏...

  • 数据结构—图的遍历

    根据图的存储方式可分为邻接矩阵的深度优先遍历和邻接表的深度优先遍历。 一、深度优先遍历 1、邻接矩阵的深度优先遍历...

  • Java遍历

    1 普通循环遍历 2 迭代器遍历 3 流遍历

  • 夯实JAVA基础之 -- Map

    Map HashMap TreeMap Map的遍历 HashMap 的遍历方式1: 遍历方式2: 遍历方式3...

网友评论

      本文标题:3、表的遍历?

      本文链接:https://www.haomeiwen.com/subject/oztsjktx.html