-- tbl_weight = { -- [xx] = { id = xx, weight = xx }, -- ... -- } -- https://github.com/kinbei/lua-misc/blob/master/weighted_random.lua return function(tbl_weight, random_func, id, weight) random_func = random_func or math.random id = id or "id" weight = weight or "weight" local t = {} local total_index = #tbl_weight local total_weight = 0 for _, v in pairs(tbl_weight) do assert(type(v[weight]) == "number") total_weight = total_weight + v[weight] table.insert(t, { [id] = v[id], [weight] = v[weight], }) end return function() local rand_index while true do rand_index = random_func(1, total_index) if random_func(1, total_weight) < t[rand_index].weight then return t[rand_index][id] end end end end -- ---------------------------------------------------------------------------------------- -- math.randomseed( os.time() ) -- local function test_case_1() -- print("test_case_1") -- local t = {} -- table.insert(t, { id = 1, weight = 400 } ) -- table.insert(t, { id = 2, weight = 30 } ) -- table.insert(t, { id = 3, weight = 100 } ) -- table.insert(t, { id = 4, weight = 8 } ) -- table.insert(t, { id = 5, weight = 30 } ) -- table.insert(t, { id = 6, weight = 500 } ) -- table.insert(t, { id = 7, weight = 20 } ) -- table.insert(t, { id = 8, weight = 200 } ) -- table.insert(t, { id = 9, weight = 40 } ) -- table.insert(t, { id = 10, weight = 70 } ) -- table.insert(t, { id = 11, weight = 300 } ) -- table.insert(t, { id = 12, weight = 500 } ) -- table.insert(t, { id = 13, weight = 350 } ) -- table.insert(t, { id = 14, weight = 20 } ) -- table.insert(t, { id = 15, weight = 480 } ) -- table.insert(t, { id = 16, weight = 250 } ) -- table.insert(t, { id = 17, weight = 500 } ) -- table.insert(t, { id = 18, weight = 50 } ) -- table.insert(t, { id = 19, weight = 300 } ) -- table.insert(t, { id = 20, weight = 500 } ) -- local f = weighted_random(t) -- local result = {} -- for i = 1, 4648 do -- local id = f() -- result[id] = result[id] or 0 -- result[id] = result[id] + 1 -- end -- local r = {} -- for k, v in pairs(result) do -- table.insert(r, { id = k, times = v }) -- end -- table.sort(r, function(a, b) return a.times > b.times end) -- for _, v in ipairs(r) do -- print(v.id, v.times) -- end -- end -- local function test_case_2() -- print("test_case_2") -- local t = {} -- t[1] = { weight = 2000, id = 1 } -- t[2] = { weight = 2000, id = 2 } -- t[3] = { weight = 30, id = 3 } -- t[4] = { weight = 40, id = 4 } -- t[5] = { weight = 50, id = 5 } -- local f = weighted_random(t) -- local result = {} -- for i = 1, 4120 do -- local id = f() -- result[id] = result[id] or 0 -- result[id] = result[id] + 1 -- end -- local r = {} -- for k, v in pairs(result) do -- table.insert(r, { id = k, times = v }) -- end -- table.sort(r, function(a, b) return a.times > b.times end) -- for _, v in ipairs(r) do -- print(v.id, v.times) -- end -- end -- test_case_1() -- test_case_2()