在 Lua 的内置库中,table 提供了 table.remove(t,[num]) 来删除列表中的元素,因为在该函数的执行过程涉及到了内存的移动,所以在删除多个元素的时候,如果每次都调用该函数,就会造成多次内存移动。
针对这一点,对 table 进行一些删除操作上的性能优化,代码基本上是从 C# 源码中抄过来的:-D,介绍在这里,下面直接附上代码,里面注释比较清楚,有什么问题,希望能够留言指出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
| local TableUtil = {}
---从列表 t 中删除从 pos 开始的 num 个元素。 ---@t 删除元素的列表 ---@pos 开始删除索引 ---@num 要删除元素的数量,如果没有指定,则删除 pos 之后的所有元素 function TableUtil.ClearArray(t,pos,num) assert(t ~= nil,"The array:t is nil") assert(pos > 0 and pos<=#t,"The pos is out range")
--如果没有指定 num 值,则默认 pos 之后全部删除 num = num or #t
--需要删除的最后一个元素的索引 local index = 0 if num >= 0 then index = pos + num - 1 else --为了保持从尾往头删,调换头尾索引 pos,index = pos + num + 1,pos end
--对头尾索引进行限制,避免超界 index = index > #t and #t or index index = index < 1 and 1 or index pos = pos < 1 and 1 or pos
local maxn = #t - index + pos - 1
table.move(t,index+1,#t,pos)
local temp = #t while temp > maxn do table.remove(t,temp) temp = temp - 1 end end
---从列表 t 中删除,所有满足 match 条件的元素 ---@t 列表 ---@match 筛选列表 function TableUtil.RemoveAll(t,match) assert(match ~= nil,"Then match argument cannot be nil")
--找到第一个需要删除的元素的索引 num local num = 1 while(num < #t and not match(t[num])) do num = num + 1 end
--如果需要删除的索引超过列表最大索引,则表明没有满足删除条件的元素 if num > #t then return 0 end
--将 num 之后不需要删除的元素,移动到需要删除的元素之前,这样可以避免拷贝 local i = num + 1 while(i <= #t) do
while(i <= #t and match(t[i])) do i = i + 1 end
if i <= #t then t[num] = t[i] num = num + 1 i = i + 1 end end local result = #t - num + 1
--清楚需要删除的元素 ClearArray(t,num,result) return result end
return TableUtil
|