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

浙公网安备 33010602011771号