【在主画面加入捷径】
       
【选择语系】
繁中 简中

Lua 程序设计教学:表 (table)

【赞助商连结】

    表 (table) 是 Lua 唯一的数据结构,在 Lua 内部的实现上,表带有杂凑表 (hash table) 和数组 (array) 两种数据结构,Lua 会视需求自动调用适合的结构。对使用者来说,不需要去区分这些细节,当成关联式数组 (associative array) 使用即可。

    表有许多的用途:

    • 做为数组 (array)
    • 做为字典 (dictionary) 或杂凑 (hash)
    • 用于面向对象程序 (object-oriented programming)
    • 仿真其他数据结构 (data structures)

    本文着重前两者,其他的用途于后文介绍。

    做为数组

    数组 (array) 是一种以数字为索引的线性数据结构,在 Lua 中是以 table 仿真。

    以索引取值

    我们也可以用数字做为索引取值:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Retrieve the 3rd element.
    assert(arr[3] == "c")

    要注意的是,Lua 的数组从 1 开始,和大部分主流语言不同。

    以下的数组会造成空洞 (holes):

    local arr = {}
    
    arr[1] = "a"
    arr[2] = "b"
    -- arr[3] and arr[4] are nil
    arr[5] = "c"
    arr[6] = "d"

    在 Lua 程序中,空洞会造成一些意想不到的 bug,应避免。

    走访数组

    使用 for 循环搭配 ipairs函数可走访数组:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Iterate over the array.
    for i, e in ipairs(arr) do
      print(e)
    end

    也可以用数字为索引来走访数组:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Iterate over the array.
    for i = 1, #arr do
      print(arr[i])
    end

    数组长度

    Lua 用 # (number sign) 取得数组长度,见下例:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Check the length of the array.
    assert(#arr == 5)

    要注意的是,当数组后端元素皆为 nil 时,不计入长度,见下例:

    local arr = {10, 20, 30, nil, nil}
    assert(#arr == 3)

    插入元素

    利用 table.insert 可在尾端插入新的元素,见以下实例:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Check the length of the array.
    assert(#arr == 5)
    
    -- Append an element.
    table.insert(arr, "f")
    
    -- Recheck the length of the array.
    assert(#arr == 6)
    assert(arr[6] == "f")

    或是使用 arr[#arr+1] = "f" 也可从尾端插入元素。

    除了从尾端插入元素,也可从中间插入元素,见下例:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Check the length of the array.
    assert(#arr == 5)
    
    -- Insert an element at position 3.
    table.insert(arr, 3, "f")
    
    -- Recheck the length of the array.
    assert(#arr == 6)
    assert(arr[3] == "f")

    去除元素

    使用 table.remove 可以从尾端去除元素,见下例:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Check the length of the array.
    assert(#arr == 5)
    
    -- Pop an element.
    popped = table.remove(arr)
    
    -- Recheck the length of the array.
    assert(#arr == 4)
    assert(popped == "e")

    也可以从中间去除元素,见下例:

    -- Create an array.
    local arr = {"a", "b", "c", "d", "e"}
    
    -- Check the length of the array.
    assert(#arr == 5)
    
    -- Remove an element from position 2.
    removed = table.remove(arr, 2)
    
    -- Recheck the length of the array.
    assert(#arr == 4)
    assert(removed == "b")

    做为字典

    字典是一种以键/值对 (key-value pairs) 为组合的非线性数据结构,以键为索引取值。

    建立字典

    以下实例建立一个字典:

    -- Create an dictionary.
    local dict = {
      one="eins",
      two="zwei",
      three="drei"
    }
    
    -- Retrieve the value with the key.
    assert(dict["one"] == "eins")

    也可以先建立字典再逐一加入值:

    -- Create an dictionary.
    local dict = {}
    
    -- Add some key/value pairs.
    dict["one"] = "eins"
    dict["two"] = "zwei"
    dict["three"] = "drei"
    
    -- Retrieve the value with the key.
    assert(dict["one"] == "eins")

    走访字典

    可以用 for 循环搭配 pairs函数来走访字典,见下例:

    -- Create an dictionary.
    local dict = {one="eins", two="zwei", three="drei"}
    
    -- Iterate over the dictionary.
    for k, v in pairs(dict) do
      print(k .. ": " .. v)
    end

    注:pairs 用来走访字典,ipairs 用来走访数组。

    去除元素

    若要去除元素,将其值设为 nil 即可,以下是实例:

    -- Create an dictionary.
    local dict = {one="eins", two="zwei", three="drei"}
    
    -- Remove an key-value pair.
    dict["three"] = nil
    
    -- Retrieve some values.
    assert(dict["one"] == "eins")
    assert(dict["three"] == nil)
    【赞助商连结】