Module:number list/utils

local export = {}

-- Map a function over `list`, which may in fact be a list of strings, a single string or nil. In general, a single -- string is treated like a one-element list and nil is treated like a zero-element list. Any return values of the -- function will be collected into a flattened list, where a single string is again treated like a one-element list and -- nil is treated like a zero-element list. If the resulting list has one element (a string), that string will be -- returned, and if the resulting list has no elements, nil will be returned. When calling a function on a string, if -- the string has modifiers (e.g. 'vuitanta-vuit' or 'سیزده') and `include_modifiers` is not -- specified, the function is called on the part without the modifiers, and the modifiers are then tacked onto the -- return value(s) of the function. Strings with multiple modifiers such as 'سیزده' are correctly -- handled. function export.map(fun, list, include_modifiers) if list == nil then return nil end if type(list) == "table" then local retval = {} for _, item in ipairs(list) do			local mapret = export.map(fun, item, include_modifiers) if type(mapret) == "table" then for _, ret in ipairs(mapret) do					table.insert(retval, ret) end elseif mapret ~= nil then table.insert(retval, mapret) end end if #retval == 1 then return retval[1] elseif #retval == 0 then return nil else return retval end end if not include_modifiers then local term_part, tag_part = list:match("^(.*)(<.->)$") if term_part then local mapret = export.map(fun, term_part) if type(mapret) == "table" then local retval = {} for _, ret in ipairs(mapret) do table.insert(retval, ret .. tag_part) end return retval elseif mapret ~= nil then return mapret .. tag_part else return nil end end end return fun(list) end

function export.filter(fun, list, return_single_item) if type(list) ~= "table" then list = {list} end local retval = {} for _, item in ipairs(list) do		if fun(item) then table.insert(retval, item) end end if return_single_item and #retval == 1 then retval = retval[1] end return retval end

function export.append(...) local ret = {} for i=1,select('#', ...) do		local argt = select(i, ...) if type(argt) == "table" then for _, v in ipairs(argt) do				table.insert(ret, v)			end else table.insert(ret, argt) end end if #ret == 1 then return ret[1] end return ret end

function export.power_of(n, base) return (base or 1) .. string.rep("0", n) end

-- Format a number (either a Lua number or a string) in fixed point without any decimal point or scientific notation. -- `tostring` doesn't work because it converts large numbers such as 1000000000000000 to "1e+15". function export.format_fixed(number) if type(number) == "string" then return number else return ("%.0f"):format(number) end end

function export.add_thousands_separator(num, sep) num = export.format_fixed(num) if #num > 4 then local num_remainder_digits = #num % 3 if num_remainder_digits == 0 then num_remainder_digits = 3 end local left_remainder_digits = num:sub(1, num_remainder_digits) local right_power_of_3_digits = num:sub(1 + num_remainder_digits) num = left_remainder_digits .. right_power_of_3_digits:gsub("(...)", sep .. "%1") end return num end

return export