一、表

在 Lua 中,表(table) 是唯一的数据结构机制,它既是数组又是字典(关联数组),同时也是实现模块、类和对象的基础。

(一)创建和初始化

-- 创建空表
local t1 = {}

-- 创建带有初始内容的表
local t2 = { "apple", "banana", "cherry" }

(二)移除引用

t1 = {}

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

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

例如:

a ={18,name="张三"}
print(a[1])
print(a.name)
--输出 18 张三

--表b和表a指的是同一个表
b = a
print(b[1])
print(b.name)
--输出 18 张三
print(a)     --table: 00BB9C70
print(b)     --table: 00BB9C70

--a和b指的是同一个表,修改b的元素,a的也跟着变化
b.name="麻子"
print(a.name)
print(b.name)
--输出 麻子 麻子

--释放变量
a = nil
print(a)   --nil   
print(b)   --table: 00BB9C70

(三)访问元素

local t = { name = "John", age = 25, "first", "second" }

-- 访问字典元素
print(t.name)        -- "John"
print(t["age"])      -- 25

-- 访问数组元素
print(t[1])          -- "first"
print(t[2])          -- "second"

(四)修改和添加元素

local t = {}

-- 添加元素
t[1] = "first"
t["name"] = "Alice"
t.new_key = "value"

-- 修改元素
t[1] = "updated first"
t.name = "Bob"

-- 删除元素
t[1] = nil

二 、表的遍历

(一)数字 for 循环

local numbers = {10, 20, 30, 40, 50}

-- 正向遍历
for i = 1, #numbers do
    print(i, numbers[i])
end

-- 反向遍历
for i = #numbers, 1, -1 do
    print(i, numbers[i])
end

-- 间隔遍历
for i = 1, #numbers, 2 do
    print(i, numbers[i])
end

(二)迭代器遍历

1、ipairs - 遍历数组部分

ipairs 只遍历表的数组部分(连续的数字索引从1开始):

local fruits = {"apple", "banana", "cherry", "date"}

-- 只遍历数组部分
for index, value in ipairs(fruits) do
    print(index, value)
end
-- 输出:
-- 1       apple
-- 2       banana
-- 3       cherry
-- 4       date

遇到 nil 会停止:

local t = {"a", "b", nil, "d", "e"}

for i, v in ipairs(t) do
    print(i, v)
end
-- 输出:
-- 1       a
-- 2       b
-- 在 nil 处停止,不会输出 d 和 e

2、pairs - 遍历所有元素

pairs 会遍历表中的所有键值对,包括数组部分和哈希部分:

local person = {
    name = "John",
    age = 25,
    city = "New York",
    "first",  -- 数组部分
    "second"   -- 数组部分
}

-- 遍历所有键值对
for key, value in pairs(person) do
    print(key, value)
end
-- 可能的输出(顺序不确定):
-- 1       first
-- 2       second
-- name    John
-- age     25
-- city    New York

3、ipairs与pairs的区别

(1)遍历范围
  • ipairs仅遍历表的数组部分,即从1开始的连续整数索引,直到遇到第一个nil值为止。
  • pairs遍历表中的所有键值对,包括数组部分和哈希部分(非整数键)。
(2)遍历顺序
  • ipairs保证按索引顺序遍历(1,2,3,...),直到连续整数索引中断。
  • pairs的遍历顺序是不确定的,它可能以任意顺序遍历表中的键值对。
(3)性能
  • ipairs在遍历数组部分时通常比pairs更快,因为它只需要按顺序访问整数索引。
  • pairs需要处理哈希表结构,因此可能稍慢一些。
(4)使用场景
  • 当只需要遍历数组部分(连续整数索引)时,使用ipairs
  • 当需要遍历整个表(包括非整数键)时,使用pairs
(5)遇到nil值的行为
  • ipairs在遇到第一个nil值时停止遍历。
  • pairs会跳过nil值,但会遍历所有非nil的键(包括整数和非整数键)。

三、表的操作

(一)连接

方法:table.concat (table , sep , start , end)

参数说明:

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

举例:

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

--指定连接字符
print(table.concat( fruits,","))      --输出:banana,orange,apple

--指定索引来连接表中元素
print(table.concat( fruits,",",2,3))  --输出:orange,apple

(二)插入

方法:table.insert (table , pos , value)

参数说明:

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

举例:

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

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

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

--遍历表(fruits)
for k,v in pairs(fruits) do
    print(k,v)
end
--[[
输出:
1   banana
2   grapes
3   orange
4   apple
5   mango
]]

(三)移除

方法:table.remove (table , pos)

参数说明:

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

举例:

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

print("移除前最后一个元素为 ",fruits[#fruits])
--输出:移除前最后一个元素为     apple

table.remove(fruits)
print("移除后最后一个元素为 ",fruits[#fruits])
--输出:移除后最后一个元素为     orange

--遍历表(fruits)
for k,v in pairs(fruits) do
    print(k,v)
end
--[[
输出:
1   banana
2   orange
]]

(四)排序

1、升序

方法:table.sort (table , 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
]]

2、降序

方法:table.sort (table , function (a , b)

                                return a > b

                           end)

参数说明:

对给定的table进行降序排序。

举例:

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

table.sort(fruits,function(a,b)
        return a>b
end)
print("排序后")
for k,v in pairs(fruits) do
        print(k,v)
end
--[[
排序前
1       banana
2       orange
3       apple
4       grapes
排序后
1       orange
2       grapes
3       banana
4       apple
]]

3、table.sort(table,comp)中参数comp的作用

table.sort(table , comp) 中的 comp 参数是一个可选的比较函数,用于自定义排序的规则。

(1)comp 参数的基本作用

comp 函数决定了排序时元素之间的比较规则。它接收两个参数,返回一个布尔值:

function comp(a, b)
    -- 如果返回 true,表示 a 应该排在 b 前面
    -- 如果返回 false,表示 a 应该排在 b 后面
end
(2)默认行为(不使用 comp)

如果不提供 comp 函数,table.sort 使用默认的升序排序:

local numbers = {3, 1, 4, 1, 5}
table.sort(numbers)  -- 默认升序
print(table.concat(numbers, ", "))  -- 输出: 1, 1, 3, 4, 5

这等价于:

table.sort(numbers, function(a, b)
    return a < b  -- 默认比较函数
end)
(3)常见 comp 函数用法

Ⅰ、降序排序

local numbers = {3, 1, 4, 1, 5}
table.sort(numbers, function(a, b)
    return a > b  -- 降序:大的在前
end)
print(table.concat(numbers, ", "))  -- 输出: 5, 4, 3, 1, 1

Ⅱ、按字符串长度排序

local words = {"apple", "banana", "cat", "dog", "elephant"}
table.sort(words, function(a, b)
    return #a < #b  -- 按长度升序
end)
print(table.concat(words, ", "))  -- 输出: cat, dog, apple, banana, elephant

(五)最大值

table.maxn 在 Lua5.2 之后该方法已经不存在了,我们可以自己定义了 table_maxn 方法来实现获取表中的最大值。

方法:table_maxn(table)

参数说明:

从table中返回一个最大的值

举例:

--自定义table_maxn()方法
function table_maxn(t) 
    local mn=nil
    for k,v in pairs(t) do
        if mn==nil then
            mn=v
        end
        if mn<v then
            mn=v
        end
    end
    return mn
end

t={5,4,8,3,9,4,1,2.0}

print(table_maxn(t))  --输出:9

参考文档:

官方文档:Lua 5.4 参考手册 - 目录 - Lua 编程语言

参考文档:Lua table(表) | 菜鸟教程

参考视频:table表的公共操作(插入,移除,排序,拼接)_哔哩哔哩_bilibili

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐