function table.isEmpty(t) if type(t) ~= "table" then return true end return next(t) == nil end function table.random(t, o) if table.isEmpty(t) then return nil; end local c = table.getCount(t) if c == 1 then if o then return t[0], 0; end return t[1], 1; else local r = math.random(o and 0 or 1, c) return t[r], r; end end function table.insertonce(t, v) if table.hasItem(t, v) then return; end table.insert(t, v); end --- 将一个数组解压缩成几个元素 function table.unpackTable(Arr) if Arr == nil then return nil; end local f = function(...) return ... end return f(table.unpack(Arr)) end ---获取表中所有的Key function table.getKeys(t) if type(t) ~= "table" then return {} end local keys = {} for k,v in pairs(t) do keys[#keys + 1] = k end return keys end ---获取表中是否有对应Key function table.hasKey(t, k) if type(t) ~= "table" then return false end for key, value in pairs(t) do if k == key then return true end end return false end ---获取对应元素的Index function table.getIndex(t, v) if type(t) ~= "table" then return nil end for index, value in pairs(t) do if value == v then return index end end return nil end function table.removeKey(t, k) if t == nil then return nil end local v = t[k] t[k] = nil return v end function table.getCount(t) if type(t) ~= "table" then return -1 end local Length = 0 for i, v in pairs(t) do Length = Length + 1 end return Length end function table.isTablesEqual(t1, ...) local tables = { ... } log_tree('tables = ', tables) for i, v in pairs(tables) do if type(v) ~= 'table' then return false end for c, d in pairs(v) do if t1[c] ~= d then return false end end end return true end ---按Value删除表中元素 ---@generic T ---@param t table ---@return T|table function table.removeValue(t, v, all) local rs = {}; for i, c in pairs(t) do if c == v then table.insert(rs, i); if not all then break; end end end table.sort(rs, function(a, b) return a > b end) for i = #rs, 1, -1 do table.remove(t, rs[i]); end end ---@param t table 需要添加的值 ---@param k PlayerKey | any key ---@param v any value function table.addTableNum(t, k, v, l) t[k] = t[k] == nil and v or t[k] + v; if l == nil then return t[k]; end if v < 0 then if t[k] < l then t[k] = l; end else if t[k] > l then t[k] = l; end end return t[k] end function table.hasValue(t, value) if t == nil then return false end for k, v in pairs(t) do if v == value then return true end end return false end --- 检查 t 中是否全部拥有列表 tt 中的 function table.hasValues(t, tt) if t == nil then return false end local rt = table.intersection(t, tt) return table.getCount(rt) == table.getCount(tt); end --- 对两个表取交集 ---@generic T ---@param t1 table ---@param t2 table ---@return table function table.intersection(t1, t2) local ret = {}; local set = {}; for _, v in pairs(t1) do if set[v] == nil then set[v] = 1; else set[v] = set[v] + 1; end end for _, v in pairs(t2) do if set[v] and set[v] > 0 then table.insert(ret, v); set[v] = set[v] - 1; end end return ret; end function table.Swap(t, i, k) if type(t) ~= "table" then return false end local temp = t[i] t[i] = t[k] t[k] = temp end --- 打乱整个table 洗牌算法 function table.Shuffle(t) if type(t) ~= "table" then return false end if table.isEmpty(t) then return false; end if table.getCount(t) == 1 then return true; end for i = 1, #t - 1 do local SwapIndex = math.random(i + 1, #t) table.Swap(t, i, SwapIndex) end return true end function table.Rand(t) if type(t) ~= "table" or #t <= 0 then return nil end return t[math.random(#t)] end ---@generic K, V ---@param t1 table ---@param t2 table ---@return bool function table.compare(t1, t2) if t1 == nil or t2 == nil or type(t1) ~= 'table' or type(t2) ~= 'table' then return false end if table.getCount(t1) ~= table.getCount(t2) then return false; end for i, v in pairs(t1) do if type(v) == 'table' then return table.compare(t1[i], t2[i]); else if v ~= t2[i] then return false; end end end return true; end ---@generic T ---@param t table ---@param c T function table.hasItem(t, c) for i, v in pairs(t) do if v == c then return true; end end return false; end -- 拷贝table function table.DeepCopy(object) -- 已经复制过的table,key为复制源table,value为复制后的table -- 为了防止table中的某个属性为自身时出现死循环 -- 避免本该是同一个table的属性,在复制时变成2个不同的table(内容同,但是地址关系和原来的不一样了) local lookup_table = {} local function _copy(o) if type(o) ~= 'table' then -- 非table类型都直接返回 return o elseif lookup_table[o] then return lookup_table[o] end local new_table = {} lookup_table[o] = new_table for k, v in pairs(o) do new_table[_copy(k)] = _copy(v) end -- 这里直接拿mt来用是因为一般对table操作不会很粗暴的修改mt的相关内容 return setmetatable(new_table, getmetatable(object)) end return _copy(object) end function table.GetMaxValueResKey(t, fun) if fun == nil then fun = function(p1, p2) return p1 < p2 end end if type(t) ~= "table" or type(fun) ~= "function" or table.getCount(t) <= 0 then return end local res = nil for k, v in pairs(t) do if not res or fun(t[res], v) then res = k end end return res end function table.FindKey(t, value) if type(t) ~= "table" then return nil end for k, v in pairs(t) do if v == value then return k end end return nil end function table.GetMaxValue(t) if type(t) ~= "table" then return nil end local Res = nil for k, v in pairs(t) do if Res == nil then Res = v elseif Res < v then Res = v end end return Res end ---@generic T, U ---@param t T ---@param f string |fun(t: T, ...:U):any? ---@vararg U function table.func(t, f, ...) if t ~= nil then if type(f) == 'function' then return f(t, ...); elseif type(f) == 'string' then if t[f] ~= nil then return table.func(t, t[f], ...); end end end end -- 递归的向下找到对应的值,仅限第一个 function table.getValue(t, k, isNest) for i, v in pairs(t) do if i == k then return v; end if isNest then if type(v) == 'table' then return table.getValue(v, k, isNest); end end end return nil; end -- log输出格式化 local function logPrint(str) str = os.date("\nLog output date: %Y-%m-%d %H:%M:%S \n", os.time()) .. str print(str) end -- key值格式化 local function formatKey(key) local t = type(key) if t == "number" then return "[" .. key .. "]" elseif t == "string" then local n = tonumber(key) if n then return "[" .. key .. "]" end end return key end -- 栈 local function newStack() local stack = { tableList = {} } function stack:push(t) table.insert(self.tableList, t) end function stack:pop() return table.remove(self.tableList) end function stack:contains(t) for _, v in ipairs(self.tableList) do if v == t then return true end end return false end return stack end -- 输出打印table表 函数 function table.printTable(...) local args = {...} local function table2String(temp, stack, t, depth) stack:push(t) if type(depth) == "number" then depth = depth + 1 else depth = 1 end local indent = "" for i = 1, depth do indent = indent .. " " end for k, v in pairs(t) do local key = tostring(k) local typeV = type(v) if typeV == "table" then if key ~= "__valuePrototype" then if stack:contains(v) then table.insert(temp, indent .. formatKey(key) .. " = {检测到循环引用!},\n") else table.insert(temp, indent .. formatKey(key) .. " = {\n") table2String(temp, stack, v, depth) table.insert(temp, indent .. "},\n") end end elseif typeV == "string" then table.insert(temp, string.format("%s%s = \"%s\",\n", indent, formatKey(key), tostring(v))) else table.insert(temp, string.format("%s%s = %s,\n", indent, formatKey(key), tostring(v))) end end stack:pop() end for k, v in pairs(args) do local root = v if type(root) == "table" then local temp = {"------------------------ printTable start ------------------------\n", "local tableValue" .. " = {\n"} local stack = newStack() table2String(temp, stack, root) table.insert(temp, "}\n------------------------- printTable end -------------------------") logPrint(table.concat(temp)) else logPrint("----------------------- printString start ------------------------\n" .. tostring(root) .. "\n------------------------ printString end -------------------------") end end end