如何在Lua中遍历表?

85

所以,我有一个表格,大致如下:

arr =
{
  apples = { 'a', "red", 5 },
  oranges = { 'o', "orange", 12 },
  pears = { 'p', "green", 7 }
}

看起来无法根据索引访问它们,而且这些值本身就是表格,所以我只是将嵌套表格的第一个值作为其索引,现在它看起来像这样:

arr =
{
  apples = { 0, 'a', "red", 5 },
  oranges = { 1, 'o', "orange", 12 },
  pears = { 2, 'p', "green", 7 }
}
所以,现在每次我使用其中一个表格时,我知道索引是什么,但仍然无法使用索引访问表格,因此我开始编写一个循环遍历它们,并检查索引,直到找到正确的表格。然后我意识到......如果我不能通过索引引用它们,我怎么能循环遍历它们呢?所以,现在我卡住了。大部分时间我真的想能够输入arr.apples而不是arr[1],但当然有时需要两者都做。

1
除非在每个数组行之间加上“,”,否则@ greatwolf的答案将失败。 arr = { apples = { 0, 'a',“红色”,5 }, oranges = { 1, 'o',“橙色”,12 }, pears = { 2, 'p',“绿色”,7 }, } 可以在以下网址中看到工作示例:http://ideone.com/yWKHx7 - Kjell Hedström
@KjellHedström,我已经编辑了原帖的问题并修复了一些小的语法错误。干得好。 - greatwolf
5个回答

145

要遍历表中的所有键值对,可以使用pairs

for k, v in pairs(arr) do
  print(k, v[1], v[2], v[3])
end

输出:

pears   2   p   green
apples  0   a   red
oranges 1   o   orange

编辑:请注意,Lua 并不保证表中关联部分的迭代顺序。如果您想按特定顺序访问项目,请从 arr 中检索键并进行排序。然后通过排序后的键访问 arr

local ordered_keys = {}

for k in pairs(arr) do
    table.insert(ordered_keys, k)
end

table.sort(ordered_keys)
for i = 1, #ordered_keys do
    local k, v = ordered_keys[i], arr[ ordered_keys[i] ]
    print(k, v[1], v[2], v[3])
end

输出:

  apples  a   red     5
  oranges o   orange  12
  pears   p   green   7

4
Lua不能保证表的关联部分的迭代顺序。 - greatwolf
2
@Lemony 我已经添加了一个示例,展示如何按特定顺序遍历表。 - greatwolf
1
@HenrikErlandsson - JSON对象是无序的。请参阅规范 - beatgammit
2
当Crockford写道“对象是一组无序的名称/值对”时,他的意思是JSON字符串表示具有不应依赖于顺序的对的对象。然而,JSON是一种文本交换格式,人们所谓的“JSON对象”实际上只是一个字符串,因此,是有序的。我个人认为术语“JSON对象”被过度使用了。Henrik正确地指出,想要按照JSON字符串中给定的顺序迭代的想法是有效的,但确实是“错误”的! - Ray Toal
好的,问题中给出的代码是不正确的。在每个条目数组之间必须有一个“,”。 - Kjell Hedström
显示剩余4条评论

9

如果您想通过多个键引用嵌套表,只需将它们分配给不同的键即可。这些表不会被复制,仍然引用相同的值。

arr = {}
apples = {'a', "red", 5 }
arr.apples = apples
arr[1] = apples

这段代码块让你可以遍历表格中所有的键值对(http://lua-users.org/wiki/TablesTutorial):
for k,v in pairs(t) do
 print(k,v)
end

8
对于那些想知道为什么 ipairs 不总是输出表中所有值的人,这就是原因(我本来可以在注释中解释这个问题,但我没有足够的好男孩积分)。
函数 ipairs 仅适用于具有键为 1 的元素的表格。如果有一个键为 1 的元素,则 ipairs 将尝试按顺序遍历表格,从 1 -> 2 -> 3 -> 4 等,直到它找不到下一个元素。元素的顺序并不重要。
不符合这些要求的表格将无法与 ipairs 一起使用,应改用 pairs
示例:
ipairsCompatable = {"AAA", "BBB", "CCC"}
ipairsCompatable2 = {[1] = "DDD", [2] = "EEE", [3] = "FFF"}
ipairsCompatable3 = {[3] = "work", [2] = "does", [1] = "this"}

notIpairsCompatable = {[2] = "this", [3] = "does", [4] = "not"}
notIpairsCompatable2 = {[2] = "this", [5] = "doesn't", [24] = "either"}

ipairs尽可能进行迭代,但不会遍历表中的任何其他元素。

kindofIpairsCompatable = {[2] = 2, ["cool"] = "bro", [1] = 1, [3] = 3, [5] = 5 }

打印这些表格时,以下是输出结果。为了进行比较,我还包括了pairs的输出结果。

ipairs + ipairsCompatable
1       AAA
2       BBB
3       CCC

ipairs + ipairsCompatable2
1       DDD
2       EEE
3       FFF

ipairs + ipairsCompatable3
1       this
2       does
3       work

ipairs + notIpairsCompatable

pairs + notIpairsCompatable
2       this
3       does
4       not

ipairs + notIpairsCompatable2

pairs + notIpairsCompatable2
2       this
5       doesnt
24      either

ipairs + kindofIpairsCompatable
1       1
2       2
3       3

pairs + kindofIpairsCompatable
1       1
2       2
3       3
5       5
cool    bro

2

这里所有的答案都建议使用ipairs,但要注意,它并不总是有效。

t = {[2] = 44, [4]=77, [6]=88}

--This for loop prints the table
for key,value in next,t,nil do 
  print(key,value) 
end

--This one does not print the table
for key,value in ipairs(t) do 
  print(key,value) 
end

为什么它不总是打印? - Zeruno
我是Lua的初学者,我不知道。但是在测试我的代码时遇到了这个问题。 - sgowd
@sgowd 为什么在表 't' 后面添加 ',nil' - 这是不必要的。另外,你提到的问题(实际上并不是问题)是 ipairs 返回一组基于整数的键。这意味着如果你的表具有基于字符串的键,使用 ipairs 将把它们转换为整数键。文档非常清楚地描述了这种差异。 - Seniru Pasan
1
@SeniruPasan 感谢你提醒我不要添加 ',nil';我会尝试一下。在我给出的示例中,键是基于整数的键。Baggef的答案 https://dev59.com/NmQm5IYBdhLWcg3wqwfn#60088452 更清楚地解释了为什么ipairs并不总是有效。 - sgowd

-1

大家好,我是LUA的新手,但这些答案只帮助了我一半。所以我写了自己的代码。

for i in pairs(actions) do 
    if actions[i][3] ~= nil then
    --do something
    end
end
  1. i 是类似于 C# 中的值在表格中的索引。
  2. actions 只是表格的名称。
  3. actions[i][3] 将检查表格中所有索引,以确保它们的第三个值不为空。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接