运营要给"参加过沙巴克攻城且累计充值满 100 元"的玩家发补偿,学员对两张 500 人名单求交集时写出双循环:外层 500 乘内层 500 约 25 万次比较,耗时 2.1 毫秒还不算糟,但名单涨到 5000 人时是 2500 万次比较,直接卡死回调。求并集时又直接 table.concat 两张名单,重复玩家出现两次,补偿邮件发双份。错误场景:
local function unionBad(a, b)
local out = {}
for i, v in ipairs(a) do
out[i] = v
end
for _, v in ipairs(b) do
out[#out + 1] = v
end
return out
end
两张名单有交集时,交集玩家在并集里出现两次。
集合表法:先把一张名单装成哈希表,另一张名单查表即可——交集查得到的是交集成员,并集查不到的追加进去。圈人发补偿的完整实现。示例代码如下:
local function toSet(t)
local s = {}
for _, v in ipairs(t) do
s[v] = true
end
return s
end
local function intersect(a, b)
local sb = toSet(b)
local out = {}
for _, v in ipairs(a) do
if sb[v] then
out[#out + 1] = v
end
end
return out
end
local function union(a, b)
local sa = toSet(a)
local out = {}
for _, v in ipairs(a) do
out[#out + 1] = v
end
for _, v in ipairs(b) do
if not sa[v] then
out[#out + 1] = v
end
end
return out
end
500 人名单交集实测约 0.3 毫秒,比双循环快 7 倍;并集无重复,补偿邮件不会双发。
三步验证:两张各 500 人、重叠 120 人的名单求交集,输出条数应为 120 且与人工核对一致;并集输出应为 880 且无重复;把名单放大到 5000 人对比双循环版与集合表版耗时,差距拉大到百倍级。
差集(A 有 B 没有)是同一思路的第三种形态:遍历 A 查 B 的集合表,查不到的收集起来。示例代码如下:
local function difference(a, b)
local sb = toSet(b)
local out = {}
for _, v in ipairs(a) do
if not sb[v] then
out[#out + 1] = v
end
end
return out
end
difference(全服玩家, 已领奖玩家) 得到待提醒名单,圈人的三种集合运算一次配齐。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
设计初衷 帮会活动只有攻城与聚餐两板斧:非攻城日帮会频道冷清,成员缺乏共同目标。帮会试炼场设计:帮会自有试炼场(限时挑战波次…
设计初衷 帮会资金靠少数大佬捐献:金主一走帮会资金断崖,普通成员没有参与感也不会珍惜帮会资源。帮会会费设计:成员按职位每周缴…
设计初衷 帮会扩张靠熟人拉人:增长有天花板、新人质量参差、老人不愿带新。募兵编制设计:帮会发布募兵任务包(新人完成入帮任务即…
底层原理 协程体内出错时 resume 返回 ok=false 与错误对象,但协程体若死循环则 resume 永久挂起——错…
底层原理 coroutine.resume 的实参会在协程内成为首个 yield 的返回值;coroutine.yield …
业务场景 挂摊卖药每小时断货:玩家下线前上满货,两小时后摊位空转。摊位自动补货封装:上摊时设定补货仓库(背包或帮会仓),定时…