假设我想存储一个元素列表。包括一些零值。值的位置很重要,我需要表示列表中给定位置没有值。
这里有一个问题:
a = {1,2,3,nil,4}
for k,v in ipairs(a) do
  print(k,v)
end
print(a[4]) 
print(a[5])
for 循环只会打印元素 1,2 和 3。它在 nil 处停止。第一个打印语句打印 nil,但我不确定它是否实际存储在表中。(谁知道?)第二个打印语句按预期打印 4。
那么问题来了:如何在表中表示元素列表,并有效地遍历它们?鉴于上述条件,例如头寸是重要的,并且一些头寸是“空的”。换句话说:没有价值,但在那个位置没有那个价值是有意义的。
Lua 表可用于创建任何抽象数据结构,在您的情况下,您表示需要一个“列表”。Lua 表是一种将基于数字索引的访问与键:值访问相结合的数据结构。
根据您的示例,您正在使用表的数字索引功能,该功能允许您迭代(使用 ipairs())这些值。您将无法将 nil 放入表中,因为数字索引在第一个 nil 条目处停止。表中的其余值存储为键:值对。
有几种解决方法,但这取决于您为什么希望列表中出现 nil。最简单的方法是使用字符串“nil”而不是本机数据类型 nil。
a = {1, 2, 3, "nil", 4}
for k,v in ipairs(a) do
  print(k,v)
end
这段代码的结果是:
1   1 
2   2
3   3
4   nil
5   4
由于 Lua 实现字符串的方式,与字符串“nil”进行比较与与本机类型 nil 进行比较不会造成性能损失。
数组中的“空洞”问题(由 nil 引起)在《Lua 编程》第 5 章表中讨论。Roberto Ierusalimschy 建议跟踪阵列的大小以避免出现孔问题。
以下代码显示了跟踪列表大小的面向对象方法。这个主题有很多可能的变化。
function makeList(...)
  local list = table.pack(...)
  list.length = 
    function(self) return self.n 
    end
  list.append = 
    function(self, value)
      self.n = self.n + 1
      self[self.n] = value
    end
  list.print = 
    function(self)
      for i = 1, self.n do print(i, self[i]) end
    end
  return list
end
a = makeList(1, 2, 3, nil, 4)
a:append(5)
a:print()
print(a:length())
结果是:
1   1
2   2
3   3
4   nil
5   4
6   5
6
请注意,函数 table.pack 创建一个字段“n”,即使存在“nil”,该字段也包含正确的项目数。有关完整说明,请参阅 PIL 第 6.2 章,可变参数函数。
这是模块“null.lua”
local function null(...)
   local t, n = {...}, select('#', ...)
   for k = 1, n do
      local v = t[k]
      if     v == null then t[k] = nil
      elseif v == nil  then t[k] = null
      end
   end
   return (table.unpack or unpack)(t, 1, n)
end
_G.null = null
使用null()的编码器和解码器
require("null")
a = {null(1,2,3,nil,4)}
-- the same could be done element-by-element
-- a = {null(1),null(2),null(3),null(nil),null(4)}
for k,v in ipairs(a) do
   v = null(v)
   print(k,v)
end
print(null(a[4]))
print(null(a[5]))