表作为字典 #

一、字典基础 #

1.1 创建字典 #

lua
-- 空字典
local dict = {}

-- 初始化字典
local person = {
    name = "张三",
    age = 25,
    city = "北京"
}

-- 使用方括号初始化
local config = {
    ["host"] = "localhost",
    ["port"] = 8080,
    ["timeout"] = 30
}

1.2 键的类型 #

lua
local dict = {}

-- 字符串键(最常用)
dict.name = "Lua"

-- 数字键
dict[1] = "first"
dict[100] = "hundred"

-- 布尔键
dict[true] = "yes"
dict[false] = "no"

-- 表键
local key_table = {id = 1}
dict[key_table] = "table value"

-- 函数键(不常用)
local key_func = function() end
dict[key_func] = "function value"

-- 注意:nil 不能作为键
-- dict[nil] = "error"  -- 错误

1.3 访问字典 #

lua
local person = {name = "张三", age = 25}

-- 点语法(键必须是有效标识符)
print(person.name)  -- 张三

-- 方括号语法(任意键)
print(person["name"])  -- 张三

-- 动态键
local key = "age"
print(person[key])  -- 25

二、字典操作 #

2.1 添加和修改 #

lua
local dict = {}

-- 添加
dict.name = "Lua"
dict["version"] = 5.4

-- 修改
dict.name = "Lua 5.4"

-- 批量添加
local function extend(dict, items)
    for k, v in pairs(items) do
        dict[k] = v
    end
end

extend(dict, {
    author = "PUC-Rio",
    year = 1993
})

2.2 删除 #

lua
local dict = {a = 1, b = 2, c = 3}

-- 设置为 nil
dict.b = nil

-- 检查是否删除
print(dict.b)  -- nil

-- 删除函数
local function remove_key(dict, key)
    local value = dict[key]
    dict[key] = nil
    return value
end

2.3 检查键是否存在 #

lua
local dict = {name = "Lua", version = 5.4}

-- 方法1:与 nil 比较
if dict.name ~= nil then
    print("name 存在")
end

-- 方法2:直接判断(注意:false 也是有效值)
if dict.name then
    print("name 存在且不为 nil/false")
end

-- 方法3:检查值为 false 的情况
local function has_key(dict, key)
    return dict[key] ~= nil
end

-- 方法4:使用 rawget(避免 __index)
if rawget(dict, "name") ~= nil then
    print("name 存在")
end

三、字典遍历 #

3.1 pairs 遍历 #

lua
local dict = {a = 1, b = 2, c = 3}

-- 基本遍历
for k, v in pairs(dict) do
    print(k, v)
end

-- 只遍历键
for k in pairs(dict) do
    print(k)
end

-- 只遍历值
for _, v in pairs(dict) do
    print(v)
end

3.2 有序遍历 #

lua
-- 按键排序遍历
local function sorted_pairs(t)
    local keys = {}
    for k in pairs(t) do
        table.insert(keys, k)
    end
    table.sort(keys)
    
    local i = 0
    return function()
        i = i + 1
        local k = keys[i]
        if k then
            return k, t[k]
        end
    end
end

local dict = {c = 3, a = 1, b = 2}
for k, v in sorted_pairs(dict) do
    print(k, v)
end
-- a    1
-- b    2
-- c    3

3.3 按值排序遍历 #

lua
local function sorted_by_value(t)
    local items = {}
    for k, v in pairs(t) do
        table.insert(items, {key = k, value = v})
    end
    
    table.sort(items, function(a, b)
        return a.value < b.value
    end)
    
    local i = 0
    return function()
        i = i + 1
        local item = items[i]
        if item then
            return item.key, item.value
        end
    end
end

local scores = {Alice = 85, Bob = 92, Charlie = 78}
for name, score in sorted_by_value(scores) do
    print(name, score)
end
-- Charlie    78
-- Alice      85
-- Bob        92

四、字典方法 #

4.1 获取所有键 #

lua
local function keys(t)
    local result = {}
    for k in pairs(t) do
        table.insert(result, k)
    end
    return result
end

local dict = {a = 1, b = 2, c = 3}
local ks = keys(dict)
print(table.concat(ks, ", "))  -- a, b, c(顺序不确定)

4.2 获取所有值 #

lua
local function values(t)
    local result = {}
    for _, v in pairs(t) do
        table.insert(result, v)
    end
    return result
end

local dict = {a = 1, b = 2, c = 3}
local vs = values(dict)
print(table.concat(vs, ", "))  -- 1, 2, 3(顺序不确定)

4.3 计数 #

lua
-- 计算键值对数量
local function count(t)
    local n = 0
    for _ in pairs(t) do
        n = n + 1
    end
    return n
end

local dict = {a = 1, b = 2, c = 3}
print(count(dict))  -- 3

4.4 判断是否为空 #

lua
local function is_empty(t)
    return next(t) == nil
end

print(is_empty({}))    -- true
print(is_empty({a=1})) -- false

五、字典合并 #

5.1 合并两个字典 #

lua
local function merge(t1, t2)
    local result = {}
    for k, v in pairs(t1) do
        result[k] = v
    end
    for k, v in pairs(t2) do
        result[k] = v
    end
    return result
end

local a = {x = 1, y = 2}
local b = {y = 20, z = 3}
local c = merge(a, b)
print(c.x, c.y, c.z)  -- 1    20    3

5.2 深度合并 #

lua
local function deep_merge(t1, t2)
    local result = {}
    
    for k, v in pairs(t1) do
        if type(v) == "table" and type(t2[k]) == "table" then
            result[k] = deep_merge(v, t2[k])
        else
            result[k] = v
        end
    end
    
    for k, v in pairs(t2) do
        if result[k] == nil then
            result[k] = v
        end
    end
    
    return result
end

六、字典应用 #

6.1 计数器 #

lua
local function word_count(text)
    local counts = {}
    for word in string.gmatch(text:lower(), "%a+") do
        counts[word] = (counts[word] or 0) + 1
    end
    return counts
end

local text = "hello world hello lua world world"
local counts = word_count(text)
for word, count in pairs(counts) do
    print(word, count)
end
-- hello    2
-- world    3
-- lua      1

6.2 缓存 #

lua
local function create_cache()
    local cache = {}
    
    return {
        get = function(key)
            return cache[key]
        end,
        set = function(key, value)
            cache[key] = value
        end,
        has = function(key)
            return cache[key] ~= nil
        end,
        delete = function(key)
            cache[key] = nil
        end,
        clear = function()
            cache = {}
        end
    }
end

local cache = create_cache()
cache.set("user:1", {name = "Alice"})
print(cache.get("user:1").name)  -- Alice

6.3 配置管理 #

lua
local Config = {}

Config.defaults = {
    host = "localhost",
    port = 8080,
    debug = false,
    timeout = 30
}

function Config.create(overrides)
    local config = {}
    for k, v in pairs(Config.defaults) do
        config[k] = v
    end
    if overrides then
        for k, v in pairs(overrides) do
            config[k] = v
        end
    end
    return config
end

local config = Config.create({
    port = 3000,
    debug = true
})
print(config.host, config.port, config.debug)
-- localhost    3000    true

6.4 对象池 #

lua
local function create_pool(create_fn, reset_fn)
    local pool = {}
    local available = {}
    
    return {
        acquire = function()
            if #available > 0 then
                return table.remove(available)
            end
            return create_fn()
        end,
        release = function(obj)
            reset_fn(obj)
            table.insert(available, obj)
        end,
        size = function()
            return #available
        end
    }
end

七、字典与元表 #

7.1 默认值 #

lua
local function dict_with_default(default)
    return setmetatable({}, {
        __index = function(t, k)
            return default
        end
    })
end

local dict = dict_with_default(0)
dict.a = 1
print(dict.a)  -- 1
print(dict.b)  -- 0(默认值)

7.2 只读字典 #

lua
local function readonly(t)
    local proxy = {}
    setmetatable(proxy, {
        __index = t,
        __newindex = function()
            error("字典是只读的", 2)
        end
    })
    return proxy
end

local original = {a = 1, b = 2}
local ro = readonly(original)
print(ro.a)  -- 1
-- ro.c = 3  -- 错误:字典是只读的

7.3 弱引用字典 #

lua
-- 弱键字典
local weak_keys = setmetatable({}, {__mode = "k"})

-- 弱值字典
local weak_values = setmetatable({}, {__mode = "v"})

-- 弱键弱值
local weak_both = setmetatable({}, {__mode = "kv"})

八、性能优化 #

8.1 预分配哈希槽 #

lua
-- 预分配(LuaJIT)
-- local dict = table.new(0, 100)  -- 0 数组槽,100 哈希槽

-- 普通方式
local dict = {}
for i = 1, 100 do
    dict["key" .. i] = i
end

8.2 缓存常用键 #

lua
-- 缓存键字符串
local KEY_NAME = "name"
local KEY_AGE = "age"

local person = {}
person[KEY_NAME] = "张三"
person[KEY_AGE] = 25

九、总结 #

本章介绍了 Lua 表作为字典的使用:

  1. 字典基础:创建、键类型、访问方式
  2. 字典操作:添加、修改、删除、检查
  3. 字典遍历:pairs、有序遍历
  4. 字典方法:keys、values、count
  5. 字典合并:浅合并、深合并
  6. 应用场景:计数器、缓存、配置管理
  7. 元表应用:默认值、只读、弱引用

下一章,我们将学习模块与包。

最后更新:2026-03-27