【懒人精灵】详细介绍Lua中表的用法

一、表(table)的核心定位

Lua 中的表是唯一的复合数据结构,也是 Lua 最核心的特性之一。它不是传统意义上的数组/哈希表,而是一种“关联数组”——可以用任意非 nil 值(数字、字符串、布尔、函数、表等)作为键(key),关联任意类型的值(value),同时兼具数组、字典、对象、模块等多种角色。

表的本质是引用类型:创建表时返回的是内存地址,赋值/传参仅传递引用,而非拷贝。

local t1 = {a = 1}
local t2 = t1 -- t2和t1指向同一个表
t2.a = 2
print(t1.a) -- 输出2(引用传递)

二、表的基础用法

1. 表的创建

有两种核心创建方式:字面量创建(最常用)和 table.new()(需 LuaJIT 扩展)。

(1)字面量创建

支持“数组式”“字典式”混合定义,键默认省略时为数字索引(从 1 开始)。

-- 空表
local t = {}

-- 数组式(数字键,默认1开始)
local arr = {10, 20, 30} -- 等价于 {[1]=10, [2]=20, [3]=30}

-- 字典式(显式键)
local dict = {
    name = "Lua", -- 等价于 ["name"] = "Lua"(字符串键可省略引号)
    version = 5.4,
    [true] = "bool key", -- 非字符串键必须用[]包裹
    [{}] = "table key"   -- 表也可作为键(实际存储的是表的引用)
}

-- 混合式
local mix = {
    1, 2, -- 数字键1、2
    x = 10, -- 字符串键"x"
    [3] = 30, -- 覆盖数字键3
    ["y.z"] = 20 -- 含特殊字符的字符串键需用[]
}
(2)动态创建

通过赋值添加键值对(表创建后可随时扩展):

local t = {}
t[1] = "a"
t["b"] = 2
t.func = function() print("hello") end -- 表中存储函数

2. 表的访问与赋值

  • 访问:t[key]t.key(仅当 key 是合法标识符时可用,如字母/数字/下划线,且不以数字开头);
  • 赋值:t[key] = valuet.key = value
  • 访问不存在的键返回 nil,赋值 nil 可删除键值对。
local t = {name = "Lua", [5] = 100}

-- 合法标识符键:两种访问方式等价
print(t.name) -- Lua
print(t["name"]) -- Lua

-- 非标识符键:必须用[]
print(t[5]) -- 100
-- print(t.5) -- 语法错误

-- 赋值与删除
t.age = 28
t[5] = nil -- 删除键5
print(t[5]) -- nil

3. 表的遍历

Lua 提供 3 种核心遍历方式,需根据场景选择:

(1)ipairs():遍历连续数字索引(从 1 开始,遇到 nil 停止)

适合纯数组式表:

local arr = {10, 20, nil, 40} -- 索引3为nil
for i, v in ipairs(arr) do
    print(i, v) -- 仅输出1→10、2→20(索引3为nil,遍历终止)
end
(2)pairs():遍历所有键值对(无序,包括数字/字符串/其他类型键)

适合字典式/混合式表:

local mix = {10, name = "Lua", [5] = 50, [true] = "bool"}
for k, v in pairs(mix) do
    print(k, v) -- 输出所有键值对,顺序不固定
end
(3)手动数字遍历(可控范围)

适合非连续数字索引的表:

local t = {[2] = 20, [4] = 40, [6] = 60}
for i = 2, 6, 2 do -- 步长2,遍历2、4、6
    print(i, t[i])
end

三、表的高级用法

1. 表作为数组(序列)

Lua 中“数组”是表的特例:键为连续数字(1~n),可通过 table 标准库操作: 函数 作用 示例
table.insert(t, v) 在数组末尾插入值 table.insert(arr, 40) → arr = {10,20,30,40}
table.insert(t, pos, v) 在指定位置插入 table.insert(arr, 2, 15) → arr = {10,15,20,30,40}
table.remove(t) 删除末尾值 table.remove(arr) → arr = {10,15,20,30}
table.remove(t, pos) 删除指定位置值 table.remove(arr, 2) → arr = {10,20,30}
table.concat(t, sep) 拼接数组元素为字符串 table.concat(arr, ",") → "10,20,30"
table.sort(t) 排序数组(默认升序) table.sort(arr) → 数组按值升序排列
local arr = {30, 10, 20}
table.sort(arr)
print(table.concat(arr, "|")) -- 10|20|30

2. 表作为对象/类(OOP 基础)

如前文所述,表可存储属性和方法,结合冒号语法(t:func() 等价于 t.func(t))模拟对象:

local obj = {
    x = 10,
    y = 20,
    getSum = function(self) -- 显式接收self
        return self.x + self.y
    end
}
-- 冒号调用:自动传递self
print(obj:getSum()) -- 30
-- 等价于
print(obj.getSum(obj)) -- 30

3. 表作为模块

Lua 中模块本质是返回表的函数,表中存储模块的函数/常量,实现代码封装:

-- 模块文件:math_utils.lua
local math_utils = {}
function math_utils.add(a, b)
    return a + b
end
function math_utils.mul(a, b)
    return a * b
end
return math_utils

-- 调用模块
local utils = require("math_utils")
print(utils.add(2, 3)) -- 5

4. 元表(metatable)与元方法

表可以关联一个“元表”,元表通过 __index(索引查找)、__newindex(赋值)、__add(加法)等元方法,扩展表的行为(如实现继承、运算符重载)。

核心操作函数:

  • setmetatable(t, mt):为表 t 设置元表 mt(仅可在创建表的同一线程设置);
  • getmetatable(t):获取表 t 的元表。
-- 元表示例:运算符重载
local t1 = {1, 2, 3}
local t2 = {4, 5, 6}
local mt = {
    __add = function(a, b) -- 重载+运算符
        local res = {}
        for i = 1, #a do
            res[i] = a[i] + b[i]
        end
        return res
    end
}
setmetatable(t1, mt)
setmetatable(t2, mt)
local t3 = t1 + t2 -- 触发__add元方法
print(table.concat(t3, ",")) -- 5,7,9

5. 表的长度运算符 #

#t 用于获取表的“长度”,规则:

  • 对连续数字索引(1~n)的数组,返回 n;
  • 对非连续数字索引/字典式表,返回“最大连续数字索引”(行为不可靠,慎用);
  • 对空表返回 0。
local arr = {10, 20, 30}
print(#arr) -- 3

local t = {[1]=10, [3]=30}
print(#t) -- 1(仅索引1连续)

四、表的注意事项

  1. 键的唯一性:同一表中键唯一,重复赋值会覆盖;
  2. nil 键:不能用 nil 作为键(t[nil] = 1 语法错误),但值可以是 nil;
  3. 内存管理:表是引用类型,无引用时会被 GC 回收;
  4. 性能:数字索引的表(数组)性能优于字符串键的表(字典),遍历/访问更快;
  5. 浅拷贝 vs 深拷贝:直接赋值是引用传递,深拷贝需手动递归复制所有层级:

    -- 浅拷贝(仅复制第一层)
    function shallowCopy(t)
       local res = {}
       for k, v in pairs(t) do
           res[k] = v
       end
       return res
    end
    
    -- 深拷贝(递归复制)
    function deepCopy(t)
       local res = {}
       for k, v in pairs(t) do
           if type(v) == "table" then
               res[k] = deepCopy(v)
           else
               res[k] = v
           end
       end
       return res
    end
1. 官方交流QQ群,添加多个不批。建议使用安卓手机或电脑申请。
飞云脚本圈: 586333520飞云脚本圈
Auto.js学习交流③群:286635606
Auto.js学习交流②群:712194666(满员)
IOS免越狱自动化测试群:691997586
2. 盗版,破解有损他人权益和违法作为,请各位会员支持正版。
3. 本站部分资源来源于用户上传和网络搜集,如有侵权请提供版权证明并联系站长删除。
4.如未特别申明,本站的技术性文章均为原创,未经授权,禁止转载/搬运等侵权行为。
5.全站所有付费服务均为虚拟商品,购买后自动发货。售出后概不接受任何理由的退、换。注册即为接受此条款。
6.如果站内内容侵犯了您的权益,请联系站长删除。
飞云脚本 » 【懒人精灵】详细介绍Lua中表的用法

企业级大数据智能营销管理系统

源码转让