local array = {} function array.find(arr, elem) if type(elem) == 'function' then for i,x in ipairs(arr) do if elem(x) then return x, i end end else for i,x in ipairs(arr) do if x == elem then return i end end end return nil end function array.any(arr, f) for i,x in ipairs(arr) do local result = f(x) if result then return result end end return false end function array.all(arr, f) for i,x in ipairs(arr) do if not f(x) then return false end end return true end -- like ipairs, but support an index to start iterating from -- idx is inclusive; the first call to the iterator will return idx function array.each(arr, idx) if idx then if type(idx) ~= 'number' then error("argument #2 to 'array.each' must be an integer if provided") end assert(idx >= 1, ("can't start iterating over an array from %d; the starting index needs to be at least 1"):format(idx)) end idx = idx and idx-1 or 0 local iter = ipairs(arr) return function() local elem idx, elem = iter(arr, idx) return idx, elem end end function array.join(a, b) local result = {} for _,v in ipairs(a) do table.insert(result, v) end for _,v in ipairs(b) do table.insert(result, v) end return result end function array.map(arr, f) local result = {} for _,v in ipairs(arr) do table.insert(result, f(v)) end return result end function array.reduce(arr, init, f) local result = init for _,v in ipairs(arr) do result = f(result, v) end return result end function array.sum(arr, f) return array.reduce(array.map(arr, f), 0, function(a, b) return a+b end) end function array.product(arr, f) return array.reduce(array.map(arr, f), 1, function(a, b) return a*b end) end function array.keep(arr, f) local result = {} for _,v in ipairs(arr) do if f(v) then table.insert(result, v) end end return result end function array.remove(arr, f) local result = {} for _,v in ipairs(arr) do if not f(v) then table.insert(result, v) end end return result end return array