table是lua 中唯一的数据结构;既可以表示 hashtable 也可表示为 array;配合元表可以定制表复杂的功能(如实现面对对象编程中的类以及相应继承的功能)
arr1 = {1,2,"abc"}
-- table.insert(table, [pos,] value) table 是要插入元素的表,pos 是可选参数,表示要插入的位置,默认为表末尾,value 是要插入的元素。
table.insert(arr1,3,33) -- 插入数据
-- 遍历数组 在 Lua 索引值是以 1 为起始
for index, value in ipairs(arr1) do
io.write("index=",index," value=",value," ") -- 打印打印不换行
-- 运行结果:index=1 value=1 index=2 value=2 index=3 value=33 index=4 value=abc
end
print()
arr2 ={
{1,11,111,1111,11111},
{2,22,222,2222}
}
-- table.remove(list [, pos]) list 表示要进行删除操作的表,pos 表示要删除的元素的位置。如果没有指定 pos 参数,则默认删除表中的最后一个元素。
table.remove(arr2[2],2)
-- 可以使用#获取数组长度 type(arr2)获取数据类型
print("arr2[1][2]",arr2[1][2],"arr2.length",#arr2,"arr2[2].length",#arr2[1],type(arr2))
-- 运行结果:arr2[1][2] 11 arr2.length 2 arr2[2].length 2 table
dict = {
k1 = "v1",
k2 = "10086",
k3 = "v3"
}
-- table.insert(dict,3,666) bad argument #2 to 'insert' (position out of bounds) 置超出了表的长度范围 (table.insert 函数无法直接用于 Lua 中的字典(或称为键值对)。table.insert 函数用于操作数组形式的表,而不是字典)
table.insert(dict,1,666)
dict["age"] = 18
dict[10] = "v4"
table.remove(dict,2) -- 不会删除,因为不存在索引为2的数据(table.remove不能根据key来删除value,需要自己写代码实现根据key删除value)
print(dict.k1,dict.k2,dict["age"],dict["k3"],dict.k4)
-- pairs函数会遍历表的所有键值对,并按照任意顺序返回键和对应的值
-- ipairs函数则用于遍历数组部分的表项。它只会遍历连续的整数键,并按照索引顺序返回索引和对应的值。
-- 这里不能用ipairs进行遍历
for index, value in pairs(dict) do
io.write("key=",index," value=",value," ")
end
print()
-- 获取 table 的长度的时候无论是使用 # 还是 table.getn 其都会在索引中断的地方停止计数,而导致无法正确取得 table 的长度。如果需要
print(#dict)
运行结果
v1 10086 18 v3 nil
key=1 value=666 key=10 value=v4 key=k2 value=10086 key=k1 value=v1 key=age value=18 key=k3 value=v3
1
在Lua中,每个table都可以关联一个metatable。metatable是一个普通的table,可以包含一些特殊的字段(也称为元方法),这些字段定义了对应操作的行为。通过设置metatable,我们可以对table对象进行元操作的重载,实现自定义的行为。
local tab = {
k1 = "v1",
k2 = "10086",
k3 = "v3"
}
local meTab = setmetatable(tab,{
__index = function (t, key)
print("_index tab.k1=",t.k1,"key=",key)
return "not find key"
end,
__newindex = function (t, key, value)
-- table.insert(t,key,value) 在这里调用insert方法也不会插入成功
print("__newindex key=",key,"value=",value)
end,
__gc = function ()
print("++++++++gc+++++++++++")
end
})
print(myTab["ss"])
myTab["sss"] = "vaa"
table.insert(myTab,1,"v11")
for key, value in pairs(myTab) do
io.write("key=",key," value=",value," ") -- 打印打印不换行
end
print()
运行结构
_index tab.k1= v1 key= ss
not find key
__newindex key= sss value= vaa
__newindex key= 1 value= v11
key=k2 value=10086 key=k1 value=v1 key=k3 value=v3 # 赋值与insert失败
++++++++gc+++++++++++
local Queue = {}
function Queue:init()
local queueData = {data = {}, head = 1, tail = 0}
-- 通过setmetatable(queueData, self) 将 queueData对象与 Queue 类关联起来,并设置元表,使 queueData对象可以调用Queue类中定义的方法。
setmetatable(queueData, self)
-- self.__index = self 设置对象的元表中的 __index 元方法,将其指向自己。目的是,在对象访问属性或方法时,如果对象本身没有该属性或方法,就会去访问元表的 __index 中指定的对象,以实现属性和方法的继承。
self.__index = self
return queueData
end
function Queue:isEmpty()
return self.head > self.tail
end
function Queue:push(value)
self.tail = self.tail + 1
self.data[self.tail] = value
end
function Queue:pop()
if self:isEmpty() then
return nil
end
local value = self.data[self.head]
self.data[self.head] = nil
self.head = self.head + 1
return value
end
使用
local myQueue = Queue:init()
myQueue:push(1)
myQueue:push("abc")
myQueue:push({1,2,3})
print(myQueue:pop()) -- 1
print(myQueue:pop()) -- abc
print(myQueue:pop()) -- table: 0x55be51926b00