Lua - create a list of numbers to pass to a function

Viewed 37

I'd like to populate the parameters/values needed for this function, using table.concat(mytable, ", ") but no matter which way I try I’m not able to alter the string of numbers returned so it’s suitable for this function? Can anyone help ?

local function min_mean_max(...)
  local min = select(1, ...)
  local max = select(1, ...) 
  local mean = 0
  -- Iterate using the numbers, no need the index variable use `_` as a placeholder
  for _, number  in ipairs({...}) do
    -- Set a new minimum if necessary
    if min > number then min = number end
    -- Set a new maximum if necessary
    if max < number then max = number end
    -- Sum the numbers to find the average
    mean = mean + number
  end
  -- Divide the numbers by their quantity
  mean = mean / #{...}
  return min, mean, max
end

For reference this works..

local min, mean, max = min_mean_max(961, 335, 342, 453, 601, 767, 889, 936)
print("Minimum, mean and maximum numbers are", min, mean, max)

I either need a different way to convert a table/array {961, 335, 342, 453, 601, 767, 889, 936} or convert a string like this “961, 335, 342, 453, 601, 767, 889, 936” ?

Or perhaps there is another route ?

1 Answers

First of all, let's rewrite min_mean_max: math.min and math.max both accept a vararg (...); there's no need to convert the vararg to a table to iterate and count it.

local function min_mean_max(...)
    local n_args = select("#", ...)
    local sum = 0
    for i = 1, n_args do sum = sum + select(i, ...) end
    return math.min(...), sum / n_args, math.max(...)
end

(this differs subtly in that it expects ... to consist of numbers, whereas the previous implementation would have accepted arbitrary objects properly overriding +, / and </>)

If you want to pass a table/array to this function, simply convert it to a vararg using table.unpack:

local min, mean, max = min_mean_max(table.unpack{961, 335, 342, 453, 601, 767, 889, 936})
print("Minimum, mean and maximum numbers are", min, mean, max)

(use unpack instead of table.unpack on Lua 5.1)

To convert a string into such a table or vararg, you would have to either split or simply extract numbers (more permissive). You don't have to manually tonumber the strings though - Lua's coercion will do that for you if you use the rewritten function. The second approach might look as follows:

local numbers = {}
for number in ("961, 335, 342, 453, 601, 767, 889, 936"):gmatch"[^,%s]+" do
    table.insert(numbers, tonumber(number)) -- for good measure: don't rely on coercion in min_mean_max
end
print(min_mean_max(numbers))
Related