table库封装了一些常用的方法,可以在日常的列表操作时提供便利,先看一下table中提供的一些方法。
方法 | 描述 |
---|---|
table.concat(list, sep, i, j) | 对数组进行拼接,返回一个字符串 |
table.insert(list, pos, value) | 将元素插入到指定的数组位置 |
table.move(a1, f, e, t, a2) | 将a1数组从f位置开始到e位置结束的元素复制到a2,从a2的t位置开始 |
table.pack(...) | 将参数封包为一个table,数组序列从1开始,同时返回一个n 的key,描述参数的数量 |
table.remove(list, pos) | 将指定位置的元素删除 |
table.sort(list, comp) | 对数组进行排序 |
table.unpack(list, i, j) | 将数组的位置i开始到j位置结束,返回数组中的元素 |
添加与删除
table.insert(t, pos, value)
可以将value插入到指定的pos位置,如果pos不是最后位置,需要移动pos以及后续的所有元素,并将value插入到空出的pos位置。如果直接调用table.insert(t, value)
,则直接将元素value添加到数组的末尾。
local t = {}
table.insert(t, "a") -- t为空,则a为第一个位置
print(t[1])
-->> a
table.insert(t, 1, "b") -- 将位置1插入元素b,原来的a元素后移指2位置
for i, v in pairs(t) do
print(i, v)
end
-->> 1 b
-->> 2 a
local a = { "a", "b", "c" }
table.insert(a, 2, "ray") -- 2位置插入ray,原来的b、c移动到位置3、4
for i, v in pairs(a) do
print(i, v)
end
-->> 1 a
-->> 2 ray
-->> 3 b
-->> 4 c
删除方法与插入方法类似,table.remove(list, pos)
,将从pos位置删除元素,并返回该位置的元素,后续的元素会前移;如果不指定pos参数,table.remove(list)
将删除最后一个元素。
local t = { "a", "b", "c", "d" }
local d = table.remove(t, 2)
print(d)
-->> b
local d2 = table.remove(t)
print(d2)
--> d
排序
对于数组排序功能较为常见,一般情况如果使用简单数组,可以直接使用table.sort(t)
,即可实现升序排序(默认为小于操作,即比较函数中第一个元素小于第二个元素);如果复杂table或者要按降序等排序,需要传递第二个参数(排序函数),降序为比较函数中第一个元素大于第二个元素。
local t = { 8, 5, 9, 3, 5, 4, 1 }
table.sort(t)
for i, v in pairs(t) do
print(i, v)
end
-->> 1 1
-->> 2 3
-->> 3 4
-->> 4 5
-->> 5 5
-->> 6 8
-->> 7 9
local a = { "g", "a", "b", "e", "z", "y" }
table.sort(a)
for i, v in pairs(a) do
print(i, v)
end
-->> 1 a
-->> 2 b
-->> 3 e
-->> 4 g
-->> 5 y
-->> 6 z
实现降序时,提供一个比较函数,function(a,b)
,其中a、b分别为数组的两个比较元素。
local a = { "g", "a", "b", "e", "z", "y" }
table.sort(a, function(i, j) -- 比较函数,降序为第一个元素参数大于第二个元素参数,升序为小于
return i > j
end)
for i, v in pairs(a) do
print(i, v)
end
-->> 1 z
-->> 2 y
-->> 3 g
-->> 4 e
-->> 5 b
-->> 6 a
排序还可以对一些复杂的table进行操作,比如有一个对象存储的为学生姓名及分数,按分数从高到低进行排序。
local students = {
{ name = "ray", score = 99 },
{ name = "hh", score = 77 },
{ name = "xx", score = 89 },
{ name = "xy", score = 90 },
{ name = "zs", score = 60 },
{ name = "ls", score = 100 },
}
table.sort(students, function(s1, s2)
return s1.score > s2.score
end)
for _, v in pairs(students) do
print(v.name, v.score)
end
-->> ls 100
-->> ray 99
-->> xy 90
-->> xx 89
-->> hh 77
-->> zs 60
移动及封包
table.move(a1, f, e, t, a2)
,可以按参数指定位置的元素复制到指定起始位置的另外一个table中,类似于数组复制。
这里,我们创建一个数组,长度为4,将从该数组的1位置到3位置共三个元素复制到b数组,b数组从2位置开始接收数据。
local a = { 4, 5, 6, 7 }
local b = {}
table.move(a, 1, 3, 2, b) -- 这里的位置参数均不能缺省
for i, v in pairs(b) do
print(i, v)
end
-->> 2 4
-->> 3 5
-->> 4 6
table.pack(...)
函数可以将一些散列的参数,封装到一个table中,并将接收的参数个数,以key=n
作为最后一个元素插入到table中,之后将该table返回给调用者。
local a = table.pack("ray", { 1, 2, 3 }, "hh", { name = "hh" })
print(a.n)
for i, v in pairs(a) do
if type(v) ~= "table" then
print(i, v)
else
for j, val in pairs(v) do -- 这里只是演示,不考虑更多层数组嵌套
print(i, j, val)
end
end
end
-->> 4 --参数长度为4
-->> 1 ray -- 第一个位置元素
-->> 2 1 1 -- 第二个位置为数组,循环数组,第二个位置为嵌套数组位置
-->> 2 2 2
-->> 2 3 3
-->> 3 hh
-->> 4 name hh -- 第四个位置为table,第二个位置为table的key
-->> n 4 -- 参数长度
table.unpack(list, i, j)
与table.pack(...)
功能相反,将一个数组拆解,并返回指定位置的元素。
local a = { "ray", { 1, 2, 3 }, "hh", { name = "hh" } }
local z, x, c, v = table.unpack(a) -- 返回全部元素
print(z,x,c,v)
-->> ray table: 0000000000199dc0 hh table: 0000000000199cc0
local x, c = table.unpack(a, 2, 3)
for i, v in pairs(x) do -- 第二个位置为table
print(i, v)
end
-->> 1 1
-->> 2 2
-->> 3 3
print(c) -- 字符串hh
-->> hh
连接
table.concat(list, sep, i, j)
函数可以将一个table指定为进行拼接,按照指定的分割符分割,返回一个字符串。在之前的章节中曾经用到过。其中分割符,位置均可省略,分割符省略时,默认为空,位置省略,则默认全部拼接。
local t = { "hello", "lua", ",", "very", "good", "!" }
print(table.concat(t, " "))
-->> hello lua , very good !
print(table.concat(t, " ", 1, 2)) -- 从table的第一个位置开始,到第二个元素进行拼接
-->> hello lua
如果数组中嵌套数组时,直接使用拼接函数将会异常。如上一小节中的实例数组:
local t = { "ray", { 1, 2, 3 }, "hh", { name = "hh" } }
print(table.concat(t, " "))
-->> invalid value (table) at index 2 in table for 'concat'
为了使连接函数更具备通用性,可以对concat进行封装,使用递归调用。(只能处理普通的数组嵌套)
local t = { "ray", { 1, 2, 3 }, "hh", { name = "hh" } }
function concat2(t)
if type(t) ~= "table" then
return t
end
-- 是数组进行数组拼接,为了无限递归,可以再次循环
local tmp = {}
for i = 1, #t do
tmp[i] = concat2(t[i])
end
-- 再次拼接,此时都是基础数组
return table.concat(tmp, " ")
end
print(concat2(t))
-->> ray 1 2 3 hh
在这个例子中,第四个元素为一个对象table,因此上述方放仍然无法拼接该table。添加对象table的支持拼接方法:
local t = { "ray", { 1, 2, 3 }, "hh", { name = "hh" } }
function concat2(t)
if type(t) ~= "table" then
return t
end
-- 是数组进行数组拼接,为了无限递归,可以再次循环
local tmp = {}
for i, v in pairs(t) do
if type(i) ~= "number" then
tmp[#tmp + 1] = i .. "=" .. concat2(v)
else
tmp[i] = concat2(v)
end
end
-- 再次拼接,此时都是基础数组
return table.concat(tmp, " ")
end
print(concat2(t))
-->> ray 1 2 3 hh name=hh