Skip to content

Instantly share code, notes, and snippets.

@Validark
Last active December 26, 2020 20:20
Show Gist options
  • Select an option

  • Save Validark/73a714fc2659ab8a4d83db0cee3dcaea to your computer and use it in GitHub Desktop.

Select an option

Save Validark/73a714fc2659ab8a4d83db0cee3dcaea to your computer and use it in GitHub Desktop.
Takes in a number or a string coercible to a number, and returns a string where every 3rd digit from the decimal point is separated by a comma
-- Takes in a number or a string coercible to a number, and returns a string where every 3rd digit from the decimal point is separated by sep (default = ",")
-- e.g. 1000 -> 1,000 and 1234567 -> 1,234,567
-- scales linearly, basically O(2n), and doesn't create any unnecessary intermediary strings
-- @author Validark
local function commify(num, sep)
local t = type(num)
if t == "number" then
num = string.format("%f", num)
elseif t ~= "string" then
error("An invalid value was passed to commify (got " .. t .. ", expected a number or a string coercible to a number)")
end
local signPos, start, nextPos = string.match(num, "^[+-]?()0*()%d+()")
if nextPos == nil
-- Don't allow trailing 0's
or signPos ~= start
-- If a string was passed in, make sure it validates as coercible to a non-scientific number
or (t == "string" and (string.match(num, "^%.%d+()", nextPos) or nextPos) <= #num)
then
error("An invalid number was passed to commify: " .. num)
end
local n = nextPos - start
if n < 4 then return num end
local k = (n - 1) % 3
local s = k + start
local chunks = { string.sub(num, 1, s) }
local count = 1
for i = s + 1, n - 3, 3 do
count = count + 1
chunks[count] = string.sub(num, i, i + 2)
end
count = count + 1
chunks[count] = string.sub(num, nextPos - 3)
return table.concat(chunks, sep or ",", 1, count)
end
return commify
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment