Lua 学习之基础篇四

table 是 Lua 的一种数据结构用来帮助我们创建不同的数据类型,如:数组、字典等。

Lua table 使用关联型数组,你可以用任意类型的值来作数组的索引,但这个值不能是 nil。

Lua table 是不固定大小的,你可以根据自己需要进行扩容。

Lua也是通过table来解决模块(module)、包(package)和对象(Object)的。 例如string.format表示使用”format”来索引table string。

table(表)的构造

构造器是创建和初始化表的表达式。表是Lua特有的功能强大的东西。最简单的构造函数是{},用来创建一个空表。可以直接初始化数组:

-- 初始化表
mytable = {}

-- 指定值
mytable[1]= "Lua"

-- 移除引用
mytable = nil 
-- lua 垃圾回收会释放内存

当我们为 table a 并设置元素,然后将 a 赋值给 b,则 a 与 b 都指向同一个内存。如果 a 设置为 nil ,则 b 同样能访问 table 的元素。如果没有指定的变量指向a,Lua的垃圾回收机制会清理相对应的内存。

-- 简单的 table
mytable = {}
print("mytable 的类型是 ",type(mytable))

mytable[1]= "Lua"
mytable["wow"] = "修改前"
print("mytable 索引为 1 的元素是 ", mytable[1])
print("mytable 索引为 wow 的元素是 ", mytable["wow"])


-- alternatetable和mytable的是指同一个 table
alternatetable = mytable
print(alternatetable)
print(mytable)

print("alternatetable 索引为 1 的元素是 ", alternatetable[1])
print("alternatetable 索引为 wow 的元素是 ", alternatetable["wow"])

alternatetable["wow"] = "修改后"

print("mytable 索引为 wow 的元素是 ", mytable["wow"])

-- 释放变量
alternatetable = nil
print("alternatetable 是 ", alternatetable)

-- mytable 仍然可以访问
print("mytable 索引为 wow 的元素是 ", mytable["wow"])

mytable = nil
print("mytable 是 ", mytable)
mytable 的类型是         table
mytable 索引为 1 的元素是      Lua
mytable 索引为 wow 的元素是    修改前
table: 0x7fd2994074f0
table: 0x7fd2994074f0
alternatetable 索引为 1 的元素是       Lua
alternatetable 索引为 wow 的元素是     修改前
mytable 索引为 wow 的元素是    修改后
alternatetable 是        nil
mytable 索引为 wow 的元素是    修改后
mytable 是       nil

Table的访问

myTable[3]          --当键是数字的时候,只有一种访问方式
myTable.name        --当键是字符串的时候有两种访问方式
myTable["name"]

Table操作

  • table.concat (list [, sep [, i [, j]]])

concat是concatenate(连锁,连接)的缩写,table.concat()函数列出参数中指定table的数组部分从start位置到end 的所有元素,元素见以指定的分隔符(sep)隔开

fruits = {"banana","orange","apple"}
-- 返回 table 连接后的字符串
print("连接后的字符串 ",table.concat(fruits))

-- 指定连接字符
print("连接后的字符串 ",table.concat(fruits,", "))

-- 指定索引来连接 table
print("连接后的字符串 ",table.concat(fruits,", ", 2,3))
连接后的字符串      bananaorangeapple
连接后的字符串         banana, orange, apple
连接后的字符串         orange, apple
  • table.insert (list, [pos,] value)

在table的数组部分指定位置(pos)插入值为value的一个元素,pos参数可选,默认为数组部分末尾

fruits = {"banana","orange","apple"}

-- 在末尾插入
table.insert(fruits,"mango")
print("索引为 4 的元素为 ",fruits[4])

-- 在索引为 2 的键处插入
table.insert(fruits,2,"grapes")
print("索引为 2 的元素为 ",fruits[2])

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

输出如下:
索引为 4 的元素为      mango
索引为 2 的元素为      grapes
1       banana
2       grapes
3       orange
4       apple
5       mango
  • table.move (a1, f, e, t [,a2])

将a1中[f,e]范围内的元素拷贝到a2[t,t+e-f]范围内,拷贝内容为a1对应下标所含内容,有则copy。

t = {"12", 34, [8] = "56", m="78", n=90}
t1 = {}
table.move(t, 1, 3, 3, t1) 
--把t中下标key为1-3的元素copy到t1 key为3-5的,t1的元素取决于t中范围内的元素
print("t: ")
    print(i, v) 
end
print("t1: ")
for i,v in pairs(t1) do 
    print(i, v) 
end
t: 
1       12
2       34
8       56
n       90
m       78
t1: 
4       34
3       12
  • table.remove (list [, pos])

返回table数组部分位于pos位置的元素,其后的元素会被前移,pos参数可选,默认为table长度,即从最后一个元素删起。

local tabLanguage = { 
    "Assemblylanguage",
    "Lua",
    "c",
    "c++",
    "swift",
    "java",
    "python",
    "ruby"
};

for k,v in pairs(tabLanguage) do
    print(k,v)
end
print("LUA>>>>>>the length of table tabLanguage :", #tabLanguage, "\n")


-- 删除元素
table.remove(tabLanguage)

table.remove(tabLanguage)
for k,v in pairs(tabLanguage) do
    print(k,v)
end
print("LUA>>>>>>the length of table tabLanguage :", #tabLanguage, "\n")


-- 删除元素
local removeitem = table.remove(tabLanguage, 3)
for k,v in pairs(tabLanguage) do
    print(k,v)
end
print("LUA>>>>>>the length of table tabLanguage :", #tabLanguage, "\n")
print("remove data of tabLanguage is : "..removeitem)

-- 元素设置nil
tabLanguage[4] = nil;
for k,v in pairs(tabLanguage) do
    print(k,v)
end
print("LUA>>>>>>the length of table tabLanguage :", #tabLanguage, "\n")
输出如下:
1       Assemblylanguage
2       Lua
3       c
4       c++
5       swift
6       java
7       python
8       ruby
LUA>>>>>>the length of table tabLanguage :    8       

1       Assemblylanguage
2       Lua
3       c
4       c++
5       swift
6       java
LUA>>>>>>the length of table tabLanguage :    6       

1       Assemblylanguage
2       Lua
3       c++
4       swift
5       java
LUA>>>>>>the length of table tabLanguage :    5       

remove data of tabLanguage is : c
1       Assemblylanguage
2       Lua
3       c++
5       java
LUA>>>>>>the length of table tabLanguage :    3
  • table.sort (list [, comp])

对给定的table 进行升序(字母或数字大小)排序

fruits = {"banana","orange","apple","grapes"}
print("排序前")
for k,v in ipairs(fruits) do
    print(k,v)
end

table.sort(fruits)
print("排序后")
for k,v in ipairs(fruits) do
    print(k,v)
end
排序前
1       banana
2       orange
3       apple
4       grapes
排序后
1       apple
2       banana
3       grapes
4       orange

如果有指定comp比较函数,那么sort将按照函数的规则进行排序

local tbl = {
    {id = 1, num = 88, level = 30},
    {id = 2, num = 66, level = 10},
    {id = 3, num = 66, level = 90},
    {id = 4, num = 99, level = 20},
    {id = 5, num = 66, level = 90}
}
 
table.sort(tbl, function(a, b)
    if a.num > b.num then
        -- 按num降序
        return true
    elseif a.num == b.num then
        -- 如果num相等,按level升序
        if a.level < b.level then
            return true
        elseif a.level == b.level then
            -- 如果level相等,按id降序
            return a.id > b.id
        end
    end
    return false
end)
 
for _, v in pairs(tbl) do
    print(string.format("id = %d, num = %d, level = %d", v.id, v.num, v.level))
end
 
-- id = 4, num = 99, level = 20
-- id = 1, num = 88, level = 30
-- id = 2, num = 66, level = 10
-- id = 5, num = 66, level = 90
-- id = 3, num = 66, level = 90


Table的遍历

Lua 中有默认三种方式遍历,其中pairs用于迭代元素,ipairs用于迭代数组

关于table-hash内部原理的介绍请参考:table-hash详解

  • for k,v in pairs(tbtest) do

    但是这种遍历不是有序输出

tbtest = {  
    [1] = 1,  
    [2] = 2,  
    [3] = 3,  
    [4] = 4,  
} 
 
for key, value in pairs(tbtest) do  
    print(value)  
end


4
1
2
3
  • 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
  • for i=1, #(tbtest) do

'#'是用来获取table的长度,但这种遍历方式只能遍历当tbtest中存在key为1的value时才会出现结果,而且是按照key从1开始依次递增1的顺序来遍历,否则返回0

tbtest = {  
    ["a"] = 1,  
    ["b"] = 2,  
    ["c"] = 3,  
    }  
    print(#(tbtest)) 

 tbtest = {  
        [1] = 1,  
        [2] = 2,  
        [6] = 6,  
        }  
print(#(tbtest)) 
--0
--2