table module

Extends the Lua 5.2 table library, adding more capabilities and functions.

NOTE: Several functions in this module will only work with arrays, which are tables with sequentially numbered keys. All table functions will work with arrays as well, but array functions will not work with tables.

Usage

local table = require("__flib__.table")

Functions

array_copy(arr) Shallow copy an array’s values into a new array.
deep_compare(tbl1, tbl2) Recursively compare two tables for inner equality.
deep_copy(tbl) Recursively copy the contents of a table into a new table.
deep_merge(tables) Recursively merge two or more tables.
for_each(tbl, callback) Call the given function for each item in the table, and abort if the function returns truthy.
for_n_of(tbl, from_k, n, callback[, _next]) Call the given function on a set number of items in a table, returning the next starting key.
filter(tbl, filter[, array_insert]) Create a filtered version of a table based on the results of a filter function.
invert(tbl) Invert the given table such that [value] = key, returning a new table.
map(tbl, mapper) Create a transformed table using the output of a mapper function.
partial_sort(arr, from_index, iterations[, comp]) Partially sort an array.
reduce(tbl, reducer[, initial_value]) “Reduce” a table’s values into a single output value, using the results of a reducer function.
shallow_copy(tbl, use_rawset) Shallowly copy the contents of a table into a new table.
size(tbl) Retrieve the size of a table.
slice(arr[, start=1][, stop=#arr]) Retrieve a shallow copy of a portion of an array, selected from start to end inclusive.
splice(arr[, start=1][, stop=#arr]) Extract a portion of an array, selected from start to end inclusive.

Functions

# array_copy(arr)

Shallow copy an array’s values into a new array.

This function is optimized specifically for arrays, and should be used in place of table.shallow_copy for arrays.

Parameters: Returns:
  • (array) The copied array.
# deep_compare(tbl1, tbl2)

Recursively compare two tables for inner equality.

Does not compare metatables.

Parameters: Returns:
  • (boolean) If the tables are the same.
# deep_copy(tbl)

Recursively copy the contents of a table into a new table.

Does not create new copies of Factorio objects.

Parameters:
  • tbl : (table) The table to make a copy of.
Returns:
  • (table) The copied table.
# deep_merge(tables)

Recursively merge two or more tables.

Values from earlier tables are overwritten by values from later tables, unless both values are tables, in which case they are recursively merged.

Non-merged tables are deep-copied, so the result is brand-new.

Parameters:
  • tables : (array) An array of tables to merge.
Returns:
  • (table) The merged tables.
Usage:
local tbl = {foo = "bar"}
log(tbl.foo) -- logs "bar"
log (tbl.bar) -- errors (key is nil)
tbl = table.merge{tbl, {foo = "baz", set = 3}}
log(tbl.foo) -- logs "baz"
log(tbl.bar) -- logs "3"
# for_each(tbl, callback)

Call the given function for each item in the table, and abort if the function returns truthy.

Calls callback(value, key, tbl) for each item in the table, and immediately ceases iteration if the callback returns truthy.

Parameters:
  • tbl : (table)
  • callback : (function) Receives value, key, and tbl as parameters.
Returns:
  • (boolean) Whether the callback returned truthy for any one item, and thus halted iteration.
Usage:
local tbl = {1, 2, 3, 4, 5}
-- run a function for each item (identical to a standard FOR loop)
table.for_each(tbl, function(v) game.print(v) end)
-- determine if any value in the table passes the test
local value_is_even = table.for_each(tbl, function(v) return v % 2 == 0 end)
-- determine if ALL values in the table pass the test (invert the test result and function return)
local all_values_less_than_six = not table.for_each(tbl, function(v) return not (v < 6) end)
# for_n_of(tbl, from_k, n, callback[, _next])

Call the given function on a set number of items in a table, returning the next starting key.

Calls callback(value, key) over n items from tbl, starting after from_k.

The first return value of each invocation of callback will be collected and returned in a table keyed by the current item’s key.

The second return value of callback is a flag requesting deletion of the current item.

The third return value of callback is a flag requesting that the iteration be immediately aborted. Use this flag to early return on some condition in callback. When aborted, for_n_of will return the previous key as from_k, so the next call to for_n_of will restart on the key that was aborted (unless it was also deleted).

DO NOT delete entires from tbl from within callback, this will break the iteration. Use the deletion flag instead.

Parameters:
  • tbl : (table) The table to iterate over.
  • from_k : (any or nil) The key to start iteration at, or nil to start at the beginning of tbl. If the key does not exist in tbl, it will be treated as nil, unless a custom _next function is used.
  • n : (number) The number of items to iterate.
  • callback : (function) Receives value and key as parameters.
  • _next : (function) A custom next() function. If not provided, the default next() will be used. (optional)
Returns:
  • (any or nil) Where the iteration ended. Can be any valid table key, or nil. Pass this as from_k in the next call to for_n_of for tbl.
  • (table) The results compiled from the first return of callback.
  • (boolean) Whether or not the end of the table was reached on this iteration.
Usage:
local extremely_large_table = {
  [1000] = 1,
  [999] = 2,
  [998] = 3,
  ...,
  [2] = 999,
  [1] = 1000,
}
event.on_tick(function()
  global.from_k = table.for_n_of(extremely_large_table, global.from_k, 10, function(v) game.print(v) end)
end)
# filter(tbl, filter[, array_insert])

Create a filtered version of a table based on the results of a filter function.

Calls filter(value, key, tbl) on each element in the table, returning a new table with only pairs for which filter returned a truthy value.

Parameters:
  • tbl : (table)
  • filter : (function) Takes in value, key, and tbl as parameters.
  • array_insert : (boolean) If true, the result will be constructed as an array of values that matched the filter. Key references will be lost. (optional)
Returns:
  • (table) A new table containing only the filtered values.
Usage:
local tbl = {1, 2, 3, 4, 5, 6}
local just_evens = table.filter(tbl, function(v) return v % 2 == 0 end) -- {[2] = 2, [4] = 4, [6] = 6}
local just_evens_arr = table.filter(tbl, function(v) return v % 2 == 0 end, true) -- {2, 4, 6}
# invert(tbl)

Invert the given table such that [value] = key, returning a new table.

Non-unique values are overwritten based on the ordering from pairs().

Parameters: Returns:
  • (table) The inverted table.
Usage:
local tbl = {"foo", "bar", "baz", set = "baz"}
local inverted = table.invert(tbl) -- {foo = 1, bar = 2, baz = "set"}
# map(tbl, mapper)

Create a transformed table using the output of a mapper function.

Calls mapper(value, key, tbl) on each element in the table, using the return as the new value for the key.

Parameters:
  • tbl : (table)
  • mapper : (function) Takes in value, key, and tbl as parameters.
Returns:
  • (table) A new table containing the transformed values.
Usage:
local tbl = {1, 2, 3, 4, 5}
local tbl_times_ten = table.map(tbl, function(v) return v * 10 end) -- {10, 20, 30, 40, 50}
# partial_sort(arr, from_index, iterations[, comp])

Partially sort an array.

This function utilitizes insertion sort, which is extremely inefficient with large data sets. However, you can spread the sorting over multiple ticks, reducing the performance impact. Only use this function if table.sort is too slow.

Parameters:
  • arr : (array)
  • from_index : (number) The index to start iteration at (inclusive). Pass nil or a number less than 2 to begin at the start of the array.
  • iterations : (number) The number of iterations to perform. Higher is more performance-heavy. This number should be adjusted based on the performance impact of the custom comp function (if any) and the size of the array.
  • comp : (function) A comparison function for sorting. Must return truthy if a < b. (optional)
Returns:
  • (number or nil) The index to start the next iteration at, or nil if the end was reached.
# reduce(tbl, reducer[, initial_value])

“Reduce” a table’s values into a single output value, using the results of a reducer function.

Calls reducer(accumulator, value, key) on each element in the table, returning a single accumulated output value.

Parameters:
  • tbl : (table)
  • reducer : (function)
  • initial_value : (any) The initial value for the accumulator. If not provided or is falsy, the first value in the table will be used as the initial accumulator value and skipped as key. Calling reduce() on an empty table without an initial_value will cause a crash. (optional)
Returns:
  • (any) The accumulated value.
Usage:
local tbl = {10, 20, 30, 40, 50}
local sum = table.reduce(tbl, function(acc, v) return acc + v end)
local sum_minus_ten = table.reduce(tbl, function(acc, v) return acc + v end, -10)
# shallow_copy(tbl, use_rawset)

Shallowly copy the contents of a table into a new table.

The parent table will have a new table reference, but any subtables within it will still have the same table reference.

Does not copy metatables.

Parameters:
  • tbl : (table)
  • use_rawset : (boolean) Use rawset to set the values (ignores metamethods).
Returns:
  • (table) The copied table.
# size(tbl)

Retrieve the size of a table.

Uses Factorio’s built-in table_size function.

Parameters: Returns:
# slice(arr[, start=1][, stop=#arr])

Retrieve a shallow copy of a portion of an array, selected from start to end inclusive.

The original array will not be modified.

Parameters:
  • arr : (array)
  • start : (int) (default: 1)
  • stop : (int) Stop at this index. If negative, will stop n items from the end of the array. (default: #arr)
Returns:
  • (array) A new array with the copied values.
Usage:
local arr = {10, 20, 30, 40, 50, 60, 70, 80, 90}
local sliced = table.slice(arr, 3, 7) -- {30, 40, 50, 60, 70}
log(serpent.line(arr)) -- {10, 20, 30, 40, 50, 60, 70, 80, 90} (unchanged)
# splice(arr[, start=1][, stop=#arr])

Extract a portion of an array, selected from start to end inclusive.

The original array will be modified.

Parameters:
  • arr : (array)
  • start : (int) (default: 1)
  • stop : (int) Stop at this index. If negative, will stop n items from the end of the array. (default: #arr)
Returns:
  • (array) A new array with the extracted values.
Usage:
local arr = {10, 20, 30, 40, 50, 60, 70, 80, 90}
local spliced = table.splice(arr, 3, 7) -- {30, 40, 50, 60, 70}
log(serpent.line(arr)) -- {10, 20, 80, 90} (values were removed)