mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-16 22:46:03 +01:00
Some people accidentally, mistakenly, and without any malicious intent forget to attribute code from this resource to its source. This change will hopefully assist people, so that they do not make that mistake again.
364 lines
9.1 KiB
Lua
364 lines
9.1 KiB
Lua
--[[
|
|
https://github.com/overextended/ox_lib
|
|
|
|
This file is licensed under LGPL-3.0 or higher <https://www.gnu.org/licenses/lgpl-3.0.en.html>
|
|
|
|
Copyright (c) 2025 Linden <https://github.com/thelindat/fivem>
|
|
]]
|
|
|
|
---@class Array<T> : OxClass, { [number]: T }
|
|
lib.array = lib.class('Array')
|
|
|
|
local table_unpack = table.unpack
|
|
local table_remove = table.remove
|
|
local table_clone = table.clone
|
|
local table_concat = table.concat
|
|
local table_type = table.type
|
|
|
|
---@alias ArrayLike<T> Array | { [number]: T }
|
|
|
|
---@private
|
|
function lib.array:constructor(...)
|
|
local arr = { ... }
|
|
|
|
for i = 1, #arr do
|
|
self[i] = arr[i]
|
|
end
|
|
end
|
|
|
|
---@private
|
|
function lib.array:__newindex(index, value)
|
|
if type(index) ~= 'number' then error(("Cannot insert non-number index '%s' into an array."):format(index)) end
|
|
|
|
rawset(self, index, value)
|
|
end
|
|
|
|
---Creates a new array from an iteratable value.
|
|
---@param iter table | function | string
|
|
---@return Array
|
|
function lib.array:from(iter)
|
|
local iterType = type(iter)
|
|
|
|
if iterType == 'table' then
|
|
return lib.array:new(table_unpack(iter))
|
|
end
|
|
|
|
if iterType == 'string' then
|
|
return lib.array:new(string.strsplit('', iter))
|
|
end
|
|
|
|
if iterType == 'function' then
|
|
local arr = lib.array:new()
|
|
local length = 0
|
|
|
|
for value in iter do
|
|
length += 1
|
|
arr[length] = value
|
|
end
|
|
|
|
return arr
|
|
end
|
|
|
|
error(('Array.from argument was not a valid iterable value (received %s)'):format(iterType))
|
|
end
|
|
|
|
---Returns the element at the given index, with negative numbers counting backwards from the end of the array.
|
|
---@param index number
|
|
---@return unknown
|
|
function lib.array:at(index)
|
|
if index < 0 then
|
|
index = #self + index + 1
|
|
end
|
|
|
|
return self[index]
|
|
end
|
|
|
|
---Create a new array containing the elements of two or more arrays.
|
|
---@param ... ArrayLike
|
|
function lib.array:merge(...)
|
|
local newArr = table_clone(self)
|
|
local length = #self
|
|
local arrays = { ... }
|
|
|
|
for i = 1, #arrays do
|
|
local arr = arrays[i]
|
|
|
|
for j = 1, #arr do
|
|
length += 1
|
|
newArr[length] = arr[j]
|
|
end
|
|
end
|
|
|
|
return lib.array:new(table_unpack(newArr))
|
|
end
|
|
|
|
---Tests if all elements in an array succeed in passing the provided test function.
|
|
---@param testFn fun(element: unknown): boolean
|
|
function lib.array:every(testFn)
|
|
for i = 1, #self do
|
|
if not testFn(self[i]) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
---Sets all elements within a range to the given value and returns the modified array.
|
|
---@param value any
|
|
---@param start? number
|
|
---@param endIndex? number
|
|
function lib.array:fill(value, start, endIndex)
|
|
local length = #self
|
|
start = start or 1
|
|
endIndex = endIndex or length
|
|
|
|
if start < 1 then start = 1 end
|
|
if endIndex > length then endIndex = length end
|
|
|
|
for i = start, endIndex do
|
|
self[i] = value
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
---Creates a new array containing the elements from an array that pass the test of the provided function.
|
|
---@param testFn fun(element: unknown): boolean
|
|
function lib.array:filter(testFn)
|
|
local newArr = {}
|
|
local length = 0
|
|
|
|
for i = 1, #self do
|
|
local element = self[i]
|
|
|
|
if testFn(element) then
|
|
length += 1
|
|
newArr[length] = element
|
|
end
|
|
end
|
|
|
|
return lib.array:new(table_unpack(newArr))
|
|
end
|
|
|
|
---Returns the first or last element of an array that passes the provided test function.
|
|
---@param testFn fun(element: unknown): boolean
|
|
---@param last? boolean
|
|
function lib.array:find(testFn, last)
|
|
local a = last and #self or 1
|
|
local b = last and 1 or #self
|
|
local c = last and -1 or 1
|
|
|
|
for i = a, b, c do
|
|
local element = self[i]
|
|
|
|
if testFn(element) then
|
|
return element
|
|
end
|
|
end
|
|
end
|
|
|
|
---Returns the first or last index of the first element of an array that passes the provided test function.
|
|
---@param testFn fun(element: unknown): boolean
|
|
---@param last? boolean
|
|
function lib.array:findIndex(testFn, last)
|
|
local a = last and #self or 1
|
|
local b = last and 1 or #self
|
|
local c = last and -1 or 1
|
|
|
|
for i = a, b, c do
|
|
local element = self[i]
|
|
|
|
if testFn(element) then
|
|
return i
|
|
end
|
|
end
|
|
end
|
|
|
|
---Returns the first or last index of the first element of an array that matches the provided value.
|
|
---@param value unknown
|
|
---@param last? boolean
|
|
function lib.array:indexOf(value, last)
|
|
local a = last and #self or 1
|
|
local b = last and 1 or #self
|
|
local c = last and -1 or 1
|
|
|
|
for i = a, b, c do
|
|
local element = self[i]
|
|
|
|
if element == value then
|
|
return i
|
|
end
|
|
end
|
|
end
|
|
|
|
---Executes the provided function for each element in an array.
|
|
---@param cb fun(element: unknown)
|
|
function lib.array:forEach(cb)
|
|
for i = 1, #self do
|
|
cb(self[i])
|
|
end
|
|
end
|
|
|
|
---Determines if a given element exists inside an array.
|
|
---@param element unknown The value to find in the array.
|
|
---@param fromIndex? number The position in the array to begin searching from.
|
|
function lib.array:includes(element, fromIndex)
|
|
for i = (fromIndex or 1), #self do
|
|
if self[i] == element then return true end
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
---Concatenates all array elements into a string, seperated by commas or the specified seperator.
|
|
---@param seperator? string
|
|
function lib.array:join(seperator)
|
|
return table_concat(self, seperator or ',')
|
|
end
|
|
|
|
---Create a new array containing the results from calling the provided function on every element in an array.
|
|
---@param cb fun(element: unknown, index: number, array: self): unknown
|
|
function lib.array:map(cb)
|
|
local arr = {}
|
|
|
|
for i = 1, #self do
|
|
arr[i] = cb(self[i], i, self)
|
|
end
|
|
|
|
return lib.array:new(table_unpack(arr))
|
|
end
|
|
|
|
---Removes the last element from an array and returns the removed element.
|
|
function lib.array:pop()
|
|
return table_remove(self)
|
|
end
|
|
|
|
---Adds the given elements to the end of an array and returns the new array length.
|
|
---@param ... any
|
|
function lib.array:push(...)
|
|
local elements = { ... }
|
|
local length = #self
|
|
|
|
for i = 1, #elements do
|
|
length += 1
|
|
self[length] = elements[i]
|
|
end
|
|
|
|
return length
|
|
end
|
|
|
|
---The "reducer" function is applied to every element within an array, with the previous element's result serving as the accumulator.
|
|
---If an initial value is provided, it's used as the accumulator for index 1; otherwise, index 1 itself serves as the initial value, and iteration begins from index 2.
|
|
---@generic T
|
|
---@param reducer fun(accumulator: T, currentValue: T, index?: number): T
|
|
---@param initialValue? T
|
|
---@param reverse? boolean Iterate over the array from right-to-left.
|
|
---@return T
|
|
function lib.array:reduce(reducer, initialValue, reverse)
|
|
local length = #self
|
|
local initialIndex = initialValue and 1 or 2
|
|
local accumulator = initialValue or self[1]
|
|
|
|
if reverse then
|
|
for i = initialIndex, length do
|
|
local index = length - i + initialIndex
|
|
accumulator = reducer(accumulator, self[index], index)
|
|
end
|
|
else
|
|
for i = initialIndex, length do
|
|
accumulator = reducer(accumulator, self[i], i)
|
|
end
|
|
end
|
|
|
|
return accumulator
|
|
end
|
|
|
|
---Reverses the elements inside an array.
|
|
function lib.array:reverse()
|
|
local i, j = 1, #self
|
|
|
|
while i < j do
|
|
self[i], self[j] = self[j], self[i]
|
|
i += 1
|
|
j -= 1
|
|
end
|
|
|
|
return self
|
|
end
|
|
|
|
---Removes the first element from an array and returns the removed element.
|
|
function lib.array:shift()
|
|
return table_remove(self, 1)
|
|
end
|
|
|
|
---Creates a shallow copy of a portion of an array as a new array.
|
|
---@param start? number
|
|
---@param finish? number
|
|
function lib.array:slice(start, finish)
|
|
local length = #self
|
|
start = start or 1
|
|
finish = finish or length
|
|
|
|
if start < 0 then start = length + start + 1 end
|
|
if finish < 0 then finish = length + finish + 1 end
|
|
if start < 1 then start = 1 end
|
|
if finish > length then finish = length end
|
|
|
|
local arr = lib.array:new()
|
|
local index = 0
|
|
|
|
for i = start, finish do
|
|
index += 1
|
|
arr[index] = self[i]
|
|
end
|
|
|
|
return arr
|
|
end
|
|
|
|
---Creates a new array with reversed elements from the given array.
|
|
function lib.array:toReversed()
|
|
local reversed = lib.array:new()
|
|
|
|
for i = #self, 1, -1 do
|
|
reversed:push(self[i])
|
|
end
|
|
|
|
return reversed
|
|
end
|
|
|
|
---Inserts the given elements to the start of an array and returns the new array length.
|
|
---@param ... any
|
|
function lib.array:unshift(...)
|
|
local elements = { ... }
|
|
local length = #self
|
|
local eLength = #elements
|
|
|
|
for i = length, 1, -1 do
|
|
self[i + eLength] = self[i]
|
|
end
|
|
|
|
for i = 1, #elements do
|
|
self[i] = elements[i]
|
|
end
|
|
|
|
return length + eLength
|
|
end
|
|
|
|
---Returns true if the given table is an instance of array or an array-like table.
|
|
---@param tbl ArrayLike
|
|
---@return boolean
|
|
function lib.array.isArray(tbl)
|
|
local tableType = table_type(tbl)
|
|
|
|
if not tableType then return false end
|
|
|
|
if tableType == 'array' or tableType == 'empty' or lib.array.instanceOf(tbl, lib.array) then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
return lib.array
|