modlib/table.lua

408 lines
8.7 KiB
Lua
Raw Normal View History

2020-02-08 16:39:54 -08:00
-- Table helpers
2020-03-24 15:32:56 -07:00
2020-04-05 01:42:44 -07:00
function map_index(table, func)
2020-04-05 04:14:05 -07:00
return setmetatable(table, {
2020-04-05 01:42:44 -07:00
__index = function(table, key)
return rawget(table, func(key))
end,
__newindex = function(table, key, value)
rawset(table, func(key), value)
end
})
end
function set_case_insensitive_index(table)
return map_index(table, string.lower)
end
2020-12-12 06:55:09 -08:00
function nilget(table, key, ...)
assert(key ~= nil)
local function nilget(table, key, ...)
if key == nil then
return table
end
local value = table[key]
if value == nil then
return nil
end
return nilget(value, ...)
end
return nilget(table, key, ...)
end
2020-03-24 15:32:56 -07:00
-- Fisher-Yates
function shuffle(table)
for index = 1, #table - 1 do
local index_2 = math.random(index + 1, #table)
table[index], table[index_2] = table[index_2], table[index]
2020-03-24 15:32:56 -07:00
end
return table
2020-03-24 15:32:56 -07:00
end
function equals_noncircular(table_1, table_2)
local is_equal = table_1 == table_2
if is_equal or type(table_1) ~= "table" or type(table_2) ~= "table" then
2020-02-08 16:39:54 -08:00
return is_equal
end
if #table_1 ~= #table_2 then
2020-02-08 16:39:54 -08:00
return false
end
local table_keys = {}
for key_1, value_1 in pairs(table_1) do
local value_2 = table_2[key_1]
if not equals_noncircular(value_1, value_2) then
if type(key_1) == "table" then
table_keys[key_1] = value_1
2020-02-08 16:39:54 -08:00
else
return false
end
end
end
for key_2, value_2 in pairs(table_2) do
if type(key_2) == "table" then
2020-02-08 16:39:54 -08:00
local found
for table, value in pairs(table_keys) do
if equals_noncircular(key_2, table) and equals_noncircular(value_2, value) then
table_keys[table] = nil
found = true
2020-02-08 16:39:54 -08:00
break
end
end
if not found then
return false
end
else
if table_1[key_2] == nil then
2020-02-08 16:39:54 -08:00
return false
end
end
end
return true
end
function tablecopy(t)
return table.copy(t)
end
2020-03-23 12:20:43 -07:00
copy = tablecopy
2020-12-01 10:29:18 -08:00
function shallowcopy(table)
local copy = {}
for key, value in pairs(table) do
copy[key] = value
end
return copy
end
function deepcopy_noncircular(table)
local function _copy(value)
if type(value) == "table" then
return deepcopy_noncircular(value)
end
return value
end
local copy = {}
for key, value in pairs(table) do
copy[_copy(key)] = _copy(value)
end
return copy
end
function deepcopy(table)
local copies = {}
local function _deepcopy(table)
if copies[table] then
return copies[table]
end
local copy = {}
copies[table] = copy
local function _copy(value)
if type(value) == "table" then
if copies[value] then
return copies[value]
end
return _deepcopy(value)
end
return value
end
for key, value in pairs(table) do
copy[_copy(key)] = _copy(value)
end
return copy
end
return _deepcopy(table)
end
2020-12-12 07:28:52 -08:00
tablecopy = deepcopy
copy = deepcopy
2020-02-08 16:39:54 -08:00
function count(table)
local count = 0
for _ in pairs(table) do
count = count + 1
end
return count
end
function is_empty(table)
return next(table) == nil
end
function foreach(table, func)
for k, v in pairs(table) do
2020-03-23 12:20:43 -07:00
func(k, v)
end
end
function foreach_value(table, func)
for _, v in pairs(table) do
2020-03-23 12:20:43 -07:00
func(v)
end
end
function call(table, ...)
for _, func in pairs(table) do
func(...)
end
end
function icall(table, ...)
for _, func in ipairs(table) do
func(...)
end
end
function foreach_key(table, func)
for key, _ in pairs(table) do
func(key)
2020-03-23 12:20:43 -07:00
end
end
function map(table, func)
for key, value in pairs(table) do
table[key] = func(value)
2020-02-08 16:39:54 -08:00
end
return table
2020-02-08 16:39:54 -08:00
end
function map_keys(table, func)
local new_tab = {}
for key, value in pairs(table) do
new_tab[func(key)] = value
end
return new_tab
end
function process(table, func)
local results = {}
for key, value in pairs(table) do
table.insert(results, func(key,value))
2020-02-08 16:39:54 -08:00
end
return results
2020-02-08 16:39:54 -08:00
end
function call(funcs, ...)
for _, func in ipairs(funcs) do
2020-10-14 02:16:25 -07:00
func(...)
2020-02-08 16:39:54 -08:00
end
end
2020-03-23 12:20:43 -07:00
function find(list, value)
for index, other_value in pairs(list) do
if value == other_value then
return index
end
2020-02-08 16:39:54 -08:00
end
2020-03-23 12:20:43 -07:00
return false
2020-02-08 16:39:54 -08:00
end
2020-03-23 12:20:43 -07:00
contains = find
function difference(table, other_table)
local result = {}
for key, value in pairs(other_table) do
if table[value] ~= value then
result[key] = value
2020-02-08 16:39:54 -08:00
end
end
return result
end
function add_all(table, additions)
for key, value in pairs(additions) do
table[key] = value
2020-02-08 16:39:54 -08:00
end
return table
2020-02-08 16:39:54 -08:00
end
function complete(table, completions)
for key, value in pairs(completions) do
if table[key] == nil then
table[key] = value
2020-03-23 12:20:43 -07:00
end
end
return table
end
function deepcomplete(table, completions)
for key, value in pairs(completions) do
if table[key] == nil then
table[key] = value
elseif type(table[key]) == "table" and type(value) == "table" then
deepcomplete(table[key], value)
end
end
return table
2020-03-23 12:20:43 -07:00
end
function merge_tables(table, other_table)
return add_all(copy(table), other_table)
2020-03-23 12:20:43 -07:00
end
union = merge_tables
function intersection(table, other_table)
2020-03-23 12:20:43 -07:00
local result = {}
for key, value in pairs(table) do
if other_table[key] then
2020-03-23 12:20:43 -07:00
result[key] = value
end
end
return result
end
function append(table, other_table)
local length = #table
for index, value in ipairs(other_table) do
table[length + index] = value
2020-02-08 16:39:54 -08:00
end
return table
2020-02-08 16:39:54 -08:00
end
function keys(table)
2020-02-08 16:39:54 -08:00
local keys = {}
for key, _ in pairs(table) do
keys[#keys + 1] = key
2020-02-08 16:39:54 -08:00
end
return keys
end
function values(table)
2020-02-08 16:39:54 -08:00
local values = {}
for _, value in pairs(table) do
values[#values + 1] = value
2020-02-08 16:39:54 -08:00
end
return values
end
function flip(table)
local flipped = {}
for key, value in pairs(table) do
flipped[value] = key
2020-02-08 16:39:54 -08:00
end
return flipped
end
function set(table)
local flipped = {}
for _, value in pairs(table) do
flipped[value] = true
2020-02-08 16:39:54 -08:00
end
return flipped
end
function unique(table)
local lookup = {}
for _, value in pairs(table) do
lookup[value] = true
2020-02-08 16:39:54 -08:00
end
2020-02-29 03:55:02 -08:00
return keys(lookup)
2020-02-08 16:39:54 -08:00
end
function rpairs(table)
local index = #table
return function()
if index >= 1 then
local value = table[index]
index = index - 1
if value ~= nil then
return index + 1, value
2020-02-08 16:39:54 -08:00
end
end
end
end
function best_value(table, is_better_func)
local best = next(table)
if best == nil then
return
2020-02-08 16:39:54 -08:00
end
local candidate = best
while true do
candidate = next(table, candidate)
if candidate == nil then
return best
end
if is_better_func(candidate, best) then
best = candidate
2020-02-08 16:39:54 -08:00
end
end
error()
2020-02-08 16:39:54 -08:00
end
function min(table)
return best_value(table, function(value, other_value) return value < other_value end)
2020-02-08 16:39:54 -08:00
end
function max(table)
return best_value(table, function(value, other_value) return value > other_value end)
2020-02-08 16:39:54 -08:00
end
function default_comparator(value, other_value)
if value == other_value then
2020-03-23 12:20:43 -07:00
return 0
end
if value > other_value then
2020-03-23 12:20:43 -07:00
return 1
end
return -1
end
--> index if element found
--> -index for insertion if not found
2020-03-23 12:20:43 -07:00
function binary_search_comparator(comparator)
return function(list, value)
2020-03-23 12:20:43 -07:00
local min, max = 1, #list
while min <= max do
local pivot = min + math.floor((max - min) / 2)
2020-03-23 12:20:43 -07:00
local element = list[pivot]
local compared = comparator(value, element)
if compared == 0 then
return pivot
elseif compared > 0 then
min = pivot + 1
2020-03-23 12:20:43 -07:00
else
max = pivot - 1
2020-03-23 12:20:43 -07:00
end
2020-02-08 16:39:54 -08:00
end
2020-03-23 12:20:43 -07:00
return -min
end
end
binary_search = binary_search_comparator(default_comparator)
function reverse(table)
local l = #table + 1
for index = 1, math.floor(#table / 2) do
table[l - index], table[index] = table[index], table[l - index]
2020-02-08 16:39:54 -08:00
end
return table
end
function repetition(value, count)
local table = {}
for index = 1, count do
table[index] = value
end
return table
2020-02-08 16:39:54 -08:00
end