Difference between revisions of "Module:Shared"
From Melvor Idle
Falterfire (talk | contribs) (added p.fractionpair) |
(formatnum: Use faster variant of function) |
||
Line 151: | Line 151: | ||
end | end | ||
− | |||
--Adds commas | --Adds commas | ||
function p.formatnum(number) | function p.formatnum(number) | ||
− | + | if tonumber(number) == nil then | |
− | + | return number | |
− | -- | + | else |
− | + | local result = number | |
− | + | while true do | |
− | + | -- Format in blocks of 3 digits at a time until formatting is complete | |
− | + | result, k = string.gsub(result, "^(-?%d+)(%d%d%d)", '%1,%2') | |
− | + | if k == 0 then | |
+ | break | ||
+ | end | ||
+ | end | ||
+ | return result | ||
+ | end | ||
end | end | ||
Latest revision as of 09:01, 22 February 2022
Documentation for this module may be created at Module:Shared/doc
--So there are a handful of functions that I'm using in a lot of places --So rather than continue to copy across the same handful of functions to every single new module --I'm just going to unify them here --Here's how you use this: -- 1. When you're making a new module, add this near the top: -- local Shared = require( "Module:Shared" ) -- 2. When you need to make a call to one of these functions, -- just preface it with "Shared." -- So for example you could call tableCount like so: -- Shared.tableCount(data) --This whole module copied wholesale from the Warframe wiki (https://warframe.fandom.com/wiki/Module:Shared) --I removed a couple irrelevant functions, but otherwise did not change anything local p = {} -- iterator sorted by keys -- For example, if you had a table that looked something like -- data = {["Cat"] = 5, -- ["Bat"] = 4, -- ["Hat"] = 7} -- You could do -- for k, v in skpairs(data) do... -- And your loop would start with k="Bat", v=4 then go to k="Cat", v=5, -- and finally to k="Hat", v=7 --Originally snagged this from Module:VoidByReward written by User:NoBrainz function p.skpairs(t, revert) local keys = {} for k in pairs(t) do keys[#keys + 1] = k end if revert ~= nil then table.sort(keys, function(a, b) return a > b end) else table.sort(keys) end local i = 0 local iterator = function() i = i + 1 local key = keys[i] if key then return key, t[key] else return nil end end return iterator end --General purpose function for going through a table after sorting based on a custom sort order --Taken from https://stackoverflow.com/questions/15706270/sort-a-table-in-lua function p.spairs(t, order) -- collect the keys local keys = {} for k in pairs(t) do keys[#keys+1] = k end -- if order function given, sort by it by passing the table and keys a, b, -- otherwise just sort the keys if order then table.sort(keys, function(a,b) return order(t, a, b) end) else table.sort(keys) end -- return the iterator function local i = 0 return function() i = i + 1 if keys[i] then return keys[i], t[keys[i]] end end end -- conveniently shifts BLAH to Blah -- Handy when formatting data in ALL CAPS or all lower case --Originally snagged this from Module:VoidByReward written by User:NoBrainz function p.titleCase(head, tail) if tail == nil then --Split into two lines because don't want the other return from gsub local result = string.gsub(head, "(%a)([%w_']*)", p.titleCase) return result else return string.upper(head) .. string.lower(tail) end end -- Returns the number of rows in a table -- Originally snagged this from Module:VoidByReward written by User:NoBrainz -- Note from User:Cephalon Scientia: -- Length operator (#) doesn't work as expected for tables that have been -- loaded into a module by mw.loadData(). -- Use this function to get all the rows in a table regardless of them -- being keys, values, or tables -- pre : table is a table with no explicit nil values -- post: returns the size of table, ignoring keys with nil values and -- nil values themselves -- if table is not of type 'table' then return nil function p.tableCount(table) if (type(table) == 'table') then local count = 0 for _ in pairs(table) do count = count + 1 end return count else return nil end end -- Returns the number of indexed elements in a table -- pre : table is a table with no explicit nil values -- post: returns the number of indexed elements in a table -- if table is not of type 'table' then return nil function p.indexCount(table) if (type(table) == 'table') then local count = 0 for _ in ipairs(table) do count = count + 1 end return count else return nil end end --Sorts theTable based on the listed column function p.tableSort(theTable, sortCol, ascend) local new function sorter(r1, r2) if ascend then return r1[sortCol] < r2[sortCol] else return r1[sortCol] > r2[sortCol] end end table.sort(theTable, sorter) end --Splits a string based on a sent in separating character --For example calling splitString ("Lith V1 Relic", " ") would return {"Lith", "V1", "Relic"} function p.splitString(inputstr, sep) if sep == nil then sep = "%s" end local t = {} for str in string.gmatch(inputstr, "([^"..sep.."]+)") do table.insert(t, str) end return t end --Returns 'true' if a string starts with something --For example calling startsWith ("Lith V1 Relic", "Lith") would return true function p.startsWith(string1, start) return string.sub(string1, 1, string.len(start)) == start end --Adds commas function p.formatnum(number) if tonumber(number) == nil then return number else local result = number while true do -- Format in blocks of 3 digits at a time until formatting is complete result, k = string.gsub(result, "^(-?%d+)(%d%d%d)", '%1,%2') if k == 0 then break end end return result end end function p.formatNumber(frame) number = frame.args ~= nil and frame.args[1] or frame return p.formatnum(number) end function p.round(val, maxDigits, minDigits) if val == nil then return nil else if type(maxDigits) == "table" then minDigits = maxDigits[2] maxDigits = maxDigits[1] end local result = val.."" local decimals = string.find(result, "%.") if decimals ~= nil then decimals = string.len(result) - decimals else decimals = 0 end if maxDigits ~= nil and decimals > maxDigits then result = string.format("%."..maxDigits.."f", result) elseif minDigits ~= nil and decimals < minDigits then result = string.format("%."..minDigits.."f", result) end return result end end --From http://lua-users.org/wiki/SimpleRound function p.round2(num, numDecimalPlaces) local mult = 10^(numDecimalPlaces or 0) return math.floor(num * mult + 0.5) / mult end -- pre : List is a table or a string -- Item is the element that is being searched -- IgnoreCase is a boolean; if false, search is case-sensitive -- post: returns a boolean; true if element exists in List, false otherwise function p.contains(List, Item, IgnoreCase) if List == nil or Item == nil then return false end if IgnoreCase == nil then IgnoreCase = false end if type(List) == "table" then for key, value in pairs(List) do if value == Item then return true, key elseif IgnoreCase and string.upper(value) == string.upper(Item) then return true, key end end else local start = string.find(List, Item) return start ~= nil end return false end --Stolen from http://lua-users.org/wiki/StringTrim --Trims whitespace. Not quite sure how it works. --I know how it works --replaces "^%s*(.-)%s*$" with "%1" in str --^%s*(.-)%s*$ matches: --^:beginning of string --%s*:any number of spaces --(.-):any number of any character, minimum possible, saved to %1 --%s* again --$: end of string --%1 inserts the content of the parentheses --pretty simple if you know the meanings --User:Giga Martin function p.trim(str) return (str:gsub("^%s*(.-)%s*$", "%1")) end -- generic function that checks to see if a key exists in a given nested table -- added by User:Cephalon Scientia -- pre : table is a nested table -- key is a string that represents a key name -- length is a integer that represents the size of outer table; -- if omitted, length is set to size of outer table -- post: returns a boolean; true if key exists in table, false otherwise or -- if key contains a nil value function p.hasKey(table, key, length) if (length == nil) then length = p.tableCount(table) end -- iterating through outer table for i = 1, length, 1 do local elem = table[i] -- storing one of inner tables into a variable if (elem[key] ~= nil) then return true end end return false end -- copies the contents of a variable; handy for when you might want to modify an object taken from a data file -- or any other read-only variable -- Stolen from https://gist.github.com/tylerneylon/81333721109155b2d244 function p.clone(obj) if type(obj) ~= 'table' then return obj end local res = {} for k, v in pairs(obj) do res[p.clone(k)] = p.clone(v) end return res end -- Euclidean Greatest Common Divisor algorithm function p.gcd(a, b) if b ~= 0 then return p.gcd(b, a % b) else return math.abs(a) end end --Formats a pair of numbers as a reduced fraction function p.fraction(n, d) local gcd = p.gcd(n, d) return p.formatnum(n/gcd)..'/'..p.formatnum(d/gcd) end --Similar to p.fraction but returns the simplified numerator and denomerator separately without formatting function p.fractionpair(n, d) local gcd = p.gcd(n, d) return n / gcd, d / gcd end function p.timeString(timeInSeconds, shorten) local remain = timeInSeconds local days, hours, minutes = 0, 0, 0 local isShort = shorten local pieces = {} if remain >= 86400 then days = math.floor(remain / 86400) remain = remain - days * 86400 if isShort then table.insert(pieces, days..'d') elseif days > 1 then table.insert(pieces, days..' days') else table.insert(pieces, days..' day') end end if remain >= 3600 then hours = math.floor(remain / 3600) remain = remain - hours * 3600 if isShort then table.insert(pieces, hours..'h') elseif hours > 1 then table.insert(pieces, hours..' hours') else table.insert(pieces, hours..' hour') end end if remain >= 60 then minutes = math.floor(remain / 60) remain = remain - minutes * 60 if isShort then table.insert(pieces, minutes..'m') elseif minutes > 1 then table.insert(pieces, minutes..' minutes') else table.insert(pieces, minutes..' minutes') end end if remain > 0 then if isShort then table.insert(pieces, remain..'s') elseif remain > 1 then table.insert(pieces, remain..' seconds') else table.insert(pieces, remain..' second') end end return table.concat(pieces, ', ') end function p.fixPagename(pageName) local result = pageName result = string.gsub(result, "%%27", "'") result = string.gsub(result, "'", "'") return result end --Checks if two tables contain the same value with the same indices function p.tablesEqual(t1, t2) if p.tableCount(t1) ~= p.tableCount(t2) then return false end for i, val in p.skpairs(t1) do if type(val) ~= type(t2[i]) then return false elseif type(val) == 'table' then if not p.tablesEqual(val, t2[i]) then return false end elseif t2[i] ~= val then return false end end return true end --Returns a number including the sign, even if positive function p.numStrWithSign(number) if number >= 0 then return '+'..p.formatnum(number) else return p.formatnum(number) end end return p