[Closed] Generalize and shorten function: Any kind of data to float
I was just playing around with trying to shorten some of my functions, and it got me thinking; is there some creative way to take any type of input (int/float/float3/matrix/list/nestedList/color/etc) and retrieve it’s value (interpreted as floats)?
Use-case example:
-- Example: Compare numbers by specified precision
fn fn_CompareValues inVal1 inVal2 allowedOffset:0.001 =
(
-- Calculate the difference in the numbers (in full precision)
numDiff = abs(amin(#(inVal1, inVal2))-amax(#(inVal1, inVal2)))
print numDiff
-- Return a boolean (true/false) for whether they're within the allowed threshold or not
return (if (numDiff < allowedOffset) then true else false)
)
-- Similar enough?
numSimilarity = (fn_CompareValues -133.14553111971 -133.14 allowedOffset:0.01)
In this example it just takes single floats, if I want it to work with different types of inputs I could obviously just add checks for each type of data. I could also have separate (shorter) functions for different types of data, but I’m curious how short it’s possible to make a function that are able to deal with any kind of input (that actually contains numerical data).
What got me wondering is that I’ve finally gotten around to revisiting some of the (over-my-head) tips and tricks posted on here, specifically it was one of DenisT’s tricks where he used hashing to remove duplicates from a multidimensional array:
-- Remove duplicates from multidimensional array (from DenisT @ CGSociety)
stupidArray = #( #("one", 1,2,3 ), #("one", 1,2,3 ), #("two", 1,2,3 ) )
smartArray = (arrayHashes = #(); for i in stupidArray where appendIfUnique arrayHashes (getHashValue i 0) collect i)
It’s perfectly logical (when you see it) that hashing is perfect for stuff like this, but if I hadn’t seen it I doubt I’d ever have the creativity to actually get the idea of using it for that purpose Determining if two inputs are identical (or not) is obviously a different challenge than trying to find a way to actually read them (regardless of type), so I’m pretty sure there isn’t anything close to (or as cool as) the hashing-trick, but I thought maybe there was some clever stuff that could be done recursively? Or maybe there’s a smart way to “flatten” any input into a (predictable) array? If there’s no “superhack” for this I guess I’m basically asking how short it is possible to make this function?
What I’ve got so far is converting the data to strings, then extracting the numbers. It works, but I kinda feel like there should be a cleaner way to do this?
-- Example: Compare numbers by specified precision (regardless of type of input)
fn fn_CompareValues_AnyType inVal1 inVal2 allowedOffset:0.001 =
(
-- Convert the inputs into flat arrays of numbers (float)
inValsFlat = #(#(),#())
for inVal, idx in #(inVal1 as string, inVal2 as string) do
(
for i=1 to inVal.count where (findItem #("[","]","(",")",",") inVal[i]) do (inVal[i] = " ")
inValsFlat[idx] = for i in (filterString inVal " ") where (i as float != undefined) collect (i as float)
)
-- Compare the inputs
for x=1 to (if inValsFlat[1].count != inValsFlat[2].count then (return false) else inValsFlat[1].count) do
(
-- Return false if difference of the current pair is larger than allowedOffset
if (abs(amin(#(inValsFlat[1][x], inValsFlat[2][x]))-amax(#(inValsFlat[1][x], inValsFlat[2][x]))) > allowedOffset) do return false
)
-- If it gets here, the values are similar enough
return true
)
-- Compare matrices
fn_CompareValues_AnyType selection[1].transform selection[2].transform
fn closeEnough v1 v2 precision:0.001d0 =
(
abs (double v1 - double v2) < precision
)
maybe?