lua 4 使用table實現其他數據結構,並介紹遍歷方法


本文會以vector / map / set 這三種數據類型的角度來梳理 table 支持的不同遍歷方式。

 

table as std::vector

一般,C/C++中的 array / vector (下文簡稱 vector) 是沒有 key。但是在 lua 中使用了 table 這種通用結構,就引入了 key 的問題。

在這里,把想用做 vector 的 table,做一個非常重要的約定:1 初始,key 連續。由於 table 的自由度很高,這個需要開發者自己約束。

---- 新建

t = {"A", "BB", "CCC"} -- 默認的key就是1初始且連續

-- 或者
t = {} -- 建立一個空的
t[1] = 1
t[2] = 2
t[3] = 3

-- 或者
t = {  
    [1] = 1,  
    [2] = 2,  
    [3] = 3,  -- 這里逗號可有可無
}

  

---- 模擬 pushback

vector = {}
function vector.pushback(vec, val)
  vec[#vec + 1] = val
end

v = {}
vector.pushback(v, 1)
vector.pushback(v, 2)
vector.pushback(v, 3)

  

---- 遍歷,使用 ipairs,按照key從1開始,從小到大返回元素。

for key, value in ipairs(v) do
  print(key, value)
end

 

table as std::map 用key尋值,無重復。 通用情況

---- 新建

m = {["A"] = 1, ["BB"] = 2, ["CCC"] = 3} 
m = {["A"] = 1, ["BB"] = "string2", 10 = 3}  -- key 和 value 的數據類型不必相同,自由伴隨着控制的難度,一定程度上,key 和 value 推薦使用相同的類型。value 也可以是 table。handle 這種情況需要注意更多。

-- 或者
m = {} -- 建立一個空的
m[1] = 1
m[2] = 2
m["3"] = 3 -- 打印結果和 3 一樣,可以通過 type 判斷類型差別。詳見后續例子

-- 或者
m = {  
    [1] = 1,  
    [2] = 2,  
    ["3"] = 3,  -- 這里逗號可有可無
}

  

---- 模擬 insert,不會重復插入

map = {}
function map.insert(map, key, val)
  map[key] = val
end

m = {["A"] = "str1"}
map.insert(m, 1, 25)
map.insert(m, "1", 5)
map.insert(m, 1, 2)
map.insert(m, 1, 25)

---- 查詢元素,有就是1,沒有就是0

function map.have(map, key)
  if map[key] == nil then
    return false
  else
    return true
  end
end

m = {["A"] = "str1"}
map.insert(m, 1, 25)
map.insert(m, "1", 5)
map.insert(m, 1, 2)
map.insert(m, 1, 25)

print(map.have(m, "A"))
print(map.have(m, A))

------- 結果 --------
true
false

  

 

----遍歷,使用 pairs(),按照 key 的 harsh 值大小排序輸出。注意,順序這個概念在 map 中並不重要

for key, value in pairs(m) do
  print(key, type(key), value, type(value))
end

  

table as std::map 特殊情況:key 為數字,但不連續,希望從小到大遍歷,或相反。

使用迭代器(自定義的)

-- from: program in Lua
function pairsByKeys(t)
    local a = {}
    for n in pairs(t) do 
      a[#a + 1] = n 
    end
    table.sort(a) -- 默認升序
  -- table.sort(a, function(a1, a2) return a1 > a2 end) -- 降序
    local i = 0
    return function ()
        i = i + 1
        return a[i], t[a[i]]
    end
end

  

完整示例:

map = {}
function map.insert(map, key, val)
  map[key] = val
end

function map.have(map, key)
  if map[key] == nil then
    return false
  else
    return true
  end
end

-- from: program in Lua
function pairsByKeys(t)
    local a = {}
    for n in pairs(t) do 
      a[#a + 1] = n 
    end
    table.sort(a)
    local i = 0
    return function ()
        i = i + 1
        return a[i], t[a[i]]
    end
end

m = {}
map.insert(m, 1, 10)
map.insert(m, 3, 30)
map.insert(m, 9, 90)
map.insert(m, 5, 50)

print("pairsByKeys")
for key, value in pairsByKeys(m) do
  print(key, value)
end

print("pairs")
for key, value in pairs(m) do
  print(key, value)
end

----------- 結果 ------------
pairsByKeys
1	10
3	30
5	50
9	90
pairs
1	10
9	90
5	50
3	30

  

table as std::set 有序、不重復

這里的 map 和 set 的差別就是在插入的時候,需要對所有數據按照 key 排序,從小到大。在lua 里,map 已經沒有重復的 key。

---- 新建

s = {}
s = {1,2,3}
s = {"A", "B", "C"} --> 字符串排序的規則需要自己定義

---- 模擬 insert,需要指定 value 的比較方式。set 是升序排列的,key 值不可改(注意賦值方式),所以需要指定 value 的比較方式。

set = {}
function set.insert(_s, val, _f) -- _f 就是需要自定義的比較函數,作為外部參數輸入。詳見后續
  _s[#_s + 1] = val
  if #_s > 1 then
    table.sort(_s, _f)
  end
end

---- 判斷元素有無

set = {}
function set.have(s, key)
  if s[key] == nil then
    return false
  else
    return true
  end
end

---- 迭代所有元素使用:ipairs()

for key, value in ipairs(s) do
  print(key, value)
end

---- 完整示例  

set = {}
function set.insert(_s, val, _f)
  _s[#_s + 1] = val
  if #_s > 1 then
    table.sort(_s, _f)
  end
end

function set.have(s, key)
  if s[key] == nil then
    return false
  else
    return true
  end
end

-- you need to define a function to sort values in ascending order.
function f(currenyVal, nextVal)
  return currenyVal < nextVal -- number
end

s = {}
set.insert(s, 1, f)
set.insert(s, 3, f)
set.insert(s, 9, f)
set.insert(s, 5, f)

print(set.have(s, 10)) -- 判斷有無
print(set.have(s, 1))

for key, value in ipairs(s) do
  print(key, value)
end

  

 

 

table as linked lists

請參考:https://www.lua.org/pil/11.3.html

 

table as queues (隊列,先進先出,不做介紹,請參考原文)

請參考:https://www.lua.org/pil/11.4.html

 

參考

http://blog.51cto.com/rangercyh/1032925

https://www.lua.org/pil/11.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM