Lua 扩展API 系列 - WeightedRandomUtility 权重随机值
-- 加权随机工具类 local WeightedRandomUtility class(WeightedRandomUtility ) local private {} function WeightedRandomUtility:ctor() end --- 不限制重复次数随机指定数量列表 --- param weights table 权重数组 --- param count int 随机列表长度 --- return table function WeightedRandomUtility:RandomListWithoutLimit(weights, count) if count nil or count 1 then return false end local list {} for i 1, count do local index self:ReusableRandom(weights) table.insert(list, index) end return list end --- 限制重复次数随机指定数量列表 --- eg. WeightedRandomUtility:RandomListLimiSame({10, 100, 200}, 2, 4) --- 根据权重数组{10, 100, 200}随机生成一个长度为4的随机列表列表值为随机到的权重值对应索引值(1,2,3) --- 返回类似{1,1,2,3}每个值出现次数不大于2的组合 --- param weights table 权重数组 --- param samelimit int 每个权重对应索引最大重复次数 --- param listSize int 随机列表长度 --- return table 每个值最多重复samelimit次的随机列表 function WeightedRandomUtility:RandomListLimiSame(weights, samelimit, listSize) if samelimit nil or samelimit 0 or listSize nil or listSize 0 then return false end if listSize samelimit * #weights then return false end local list {} local function addToList(tb) for _, v in pairs(tb) do table.insert(list, v) end end local count 1 local left 0 if listSize % samelimit 0 then count listSize / samelimit for i 1, samelimit do addToList(self:UniquenessRandom(weights, count)) end else local limit samelimit - 1 count math.floor(listSize / samelimit) left listSize - count * limit for i 1, limit do addToList(self:UniquenessRandom(weights, count)) end addToList(self:UniquenessRandom(weights, left)) end return list end --- 不重复随机 --- 根据权重数组返回指定个数无重复值的随机列表 --- eg. WeightedRandomUtility:UniquenessRandom({10, 20, 50}, 2) --- 根据权重数组{10, 20, 50} 随机生成一个长度为2的随机列表列表值为随机到的权重值对应索引值(1,2,3) --- 返回(1,2,3)中任意两个数的组合 {1,3} --- param weights table 权重数组 --- param count int 要随机数的个数 --- return table function WeightedRandomUtility:UniquenessRandom(weights, count) if count nil then return false end local list {} for i 1, #weights do table.insert(list, i) end if count #weights then return list end local samplelist {} for i 1, count do local item {v i, k 0} item.k math.log(RandomUtil:Random()) / weights[i] table.insert(samplelist, item) end local function comp(e1, e2) return e1.k e2.k end table.sort(samplelist, comp) for i #samplelist 1, #weights do local sampScore math.log(RandomUtil:Random()) / weights[i] if sampScore samplelist[1].k then local item {v i, k sampScore} table.remove(samplelist, 1) table.insert(samplelist, item) table.sort(samplelist, comp) end end local randomValues {} for _, value in pairs(samplelist) do table.insert(randomValues, value.v) end return randomValues; end --- 可重复随机 --- 根据权重数组返回一个随机数 --- param weights table 权重数组 --- return int function WeightedRandomUtility:ReusableRandom(weights) local sum 0 local psumList {} for i 1, #weights do sum sum weights[i] table.insert(psumList, sum) end if sum 0 then return 0 end local random RandomUtil:Random(sum) for k, v in pairs(psumList) do if random v then return k end end return 0 end function WeightedRandomUtility:RandomFromArray(arr, count) local result {} local weights {} for i 1, #arr do table.insert(weights, 1) end local indexArr WeightedRandomUtil:UniquenessRandom(weights, count) for _, index in ipairs(indexArr) do table.insert(result, arr[index]) end return result end return WeightedRandomUtility