In my script, there are vector3’s as strings. Sometimes, zeroes will be negative due to floating points. When comparing the strings later on they will falsely say they aren’t equal because one string has a non-negative 0 and the other has a negative 0, even though they are technically equal.
Well, for my use it’d be nice to be able to use string manipulation to fix it. I’m going to leave the solution unchecked for a bit and if there isn’t a string based solution I’ll go this route. Thank you!
There’s no elegant way of doing it once the string has already been created, doing a check for any components that’re equal to negative zero and replacing them while the vector is still in numerical form is probably your best bet.
You can make a faulty pattern match for it. With how lua matches work, you can’t create one single match that will replace all 3 coordinates at once (and still properly account for things such as -0.1234).
If you’re willing to use 2 gsubs at once though:
-- first & second -0s final -0
str:gsub('%-0,', '0,'):gsub('%-0$', '0')
“-” is a special reserve character for string patterns in lua, so we need to escape it and turn it into a literal character by adding a % symbol in the string when we use string.gsub, this code example should do the trick for you.
local a = "50, -0, -0"
a = string.gsub(a, "%-0", "0")
print(a)
function fixNum(x: number): number
--Lua thinks -0 == 0
return x == 0 and 0 or x
end
function fixString(x: string): string
return x == "-0" and "0" or x
end
function fixVector2(v: Vector2): Vector2
return Vector2.new(fixNum(v.X), fixNum(v.Y))
end
function fixVector3(v: Vector3): Vector3
return Vector3.new(fixNum(v.X), fixNum(v.Y), fixNum(v.Z))
end
--old solution
function fixVectorStringOld(vs: string): string
local coords = {}
for _, coord in pairs(vs:split(", ")) do
table.insert(coords, fixString(coord))
end
return table.concat(coords, ", ")
end
--new solution
function fixVectorString(vs: string): string
return ({(vs..","):gsub("-0,", "0,")})[1]:sub(0, -2)
end
print(fixVectorString("0.5, -0, -2")) --0.5, 0, -2
your fixVectorString() falsely replaces negative decimals with their positive ones (as of writing)
local function fixVectorString(vs: string): string
--two lined on purpose, don't change this
local s = vs:gsub("%-0", "0")
return s
end
print(fixVectorString("-0.5, -0, -2")) -- returns "0.5, 0, -2", should return "-0.5, 0, -2"
Also it doesn’t need to be two-lined, you could’ve just done return vs:gsub("%-0", "0") and it wouldn’t have changed the output
Reverted my method to the old one, if anyone finds a pattern that doesn’t mess with cases like -0.5 tell me.
Also, it changes the output, gsub returns a tuple. Basically, instead of returning string as the fixVectorString function denotes, it would return string, number where the second number argument within that tuple is the number of substitutions made.
The reason you didn’t notice it was because you stored the function result in a variable, which ignores the second tuple argument(basically you did what I did above but outside the function).
You are correct, I noticed that it was returning the number of substitutions but didn’t think enough of it to realise that it could have an impact.
Maybe a different comment or usage of the select function would have made this clearer though.
local stringBad = "0.25, -0.5, -0"
local temp = {}
local temp2 = stringBad:gsub(" ",""):split(",")
for i = 1, 3 do
local n = tostring(temp2[i]):match("%d+%.?%d?%d?%d?")
if tonumber(n) == 0 and tostring(temp2[i]):match("%-") then
temp[i] = math.abs(tonumber(temp2[i]))
else
temp[i] = temp2[i]
end
end
local stringGood = table.concat(temp, ", ")
Don’t want to micromanage here, but like I said in my response, you can’t fix a vector string with only one :gsub, you’ll need one to match the final component.
local function fixVectorString(vs: string): string
--two lined on purpose, don't change this
--comma included on purpose so it doesn't trigger for cases like -0.5
local s = vs:gsub("-0,", "0,")
return s
end
print(fixVectorString("-0, -0, -0")) -- prints "0, 0, -0"
Also, it’s good practice to declare your functions local, unless you want to use it in a global context.