Module Table

Table manipulation.

Note: This module inherits all native-Lua table module methods unless overwritten by same-named local methods.

Module Status: Stable.

Usage:

    local Table = require('__eradicators-library__/erlib/lua/Table')()
    

Module

Table(tbl) Attaches this Table module as metatable to a table.
NIL Workaround to put values into tables.

Basic Methods

size(tbl) Counts (key → value) pairs.
array_size(tbl) The largest numeric key in the array part of this table.
range([a=1], b[, step]) Generates a DenseArray of NaturalNumbers.
values(tbl) Generates an unsorted DenseArray from the values of tbl.
keys(tbl) Generates an unsorted DenseArray from the keys of tbl.
flip(tbl) Creates a new table in which (key ↔ value) mappings are swapped.
plural(obj) Wraps the object in a table if it is not already a table.
is_equal(tbl, tbl2) Deep compare. If two tables have exactly the same content.
is_empty(tbl) Returns true if the table contains no values.
nil_if_empty(tbl) Converts empty tables into a nil value.

Search Methods

find_largest(tbl[, gtr]) Finds the largest element in a table.
find(tbl, value) Retrieves the key of a value.
next_value(tbl[, key=nil]) Fetches the next value in a table.
first_value(tbl) Shortcut to Table.next_value(tbl,nil) that doesn't return the key at all.

In-Place Methods

pop(tbl, key[, value=nil]) In-place. Removes a (key → value) pair and returns the value.
map(tbl, f[, target=nil]) In-place. Applies a function to all elements of a table.
filter(tbl, f[, target=nil]) In-place. Removes elements from a table based on a filter function.
smerge(tbl[, tbl2]) In-place. Shallow Merge. Copies data from one table into another.
insert_once(tbl, key, value) In-place. Inserts value into tbl only if no other key in the table has an == equal value.
clear(tbl, except_keys[, is_whitelist=true]) In-place. Removes all key→value mappings from a table.
overwrite(table_reference, value_table) In-place. Puts the content of one table into the reference of another.
migrate(tbl, index, migrations[, ...]) In-place. Applies a series of migration functions to sub-table.

Copy Methods

scopy(tbl) Shallow Copy. Copies the first level of the table such that all sub-table references stay identical to the original table.
dcopy(tbl[, remove_metatables=false]) Deep Copy. A copy of a table that shares none of the original table references but has the same self-referencing structure.
fcopy(tbl[, remove_metatables=false]) Full Copy. A copy of a table that shares none of the original table references and in which all formerly self-referenced sub-tables are made unique.

Other Methods

rep(tbl[, variation_count[, patterns]]) Creates patterned and unpatterened table repetitions.
remove_nil(tbl) In-place. Shallowly replaces Table.NIL keys and values with nil, deleting the affected mappings.

Conversion

to_array(tbl[, target=nil]) In-place. Converts MixedTable to SparseArray.
to_string(tbl) Alias of String.to_string.

Metamethods

__concat() Addition with + is Table.smerge().
set_metamethod(tbl, method_name, f) Set a function as metamethod of tbl.
get_metamethod(tbl, method_name) Gets the metamethod handler function of tbl.
deep_clear_metatables(tbl) Recursively removes metatables from all subtables but not from other object types.
clear_meta(tbl) Removes any metatable from a table.
popmetatable(tbl) Removes and returns the metatable.

Path Methods

TablePath Concept. A DenseArray of values that represent keys of a nested path in another table.
get(tbl, path[, default=nil]) Get the value at location path in tbl.
set(tbl, path, value) Set a new value to location path in tbl.
sget(tbl, path, default) Get the value at location path in tbl if it exists, otherwise creates it.
add(tbl, path, number) Adds a number to an existing value or creates a new value.
remove(tbl, path) Removes and returns a value from a table.
TablePatch Concept. A DenseArray consisting of a TablePath followed by a TablePatchValue.
TablePatchValue Concept.
The value part of a TablePatch is not further interpreted unless it is a MixedTable made of a TablePath that contains the mapping {self=true}.
patch(tbl, patches) Takes an array of patches and applies them to a table.

Factories

normalizer(defaults) Factory. Applies default values to tables.
TableNormalizerFunction(tbl) In-place. Applies enclosurized defaults.
remapper(mappings[, allow_tables_as_keys=false]) Factory. Moves values from one key to another.
TableRemapperFunction(tbl) In-place. Applies enclosurized re-mappings.


Module

Table(tbl)
Attaches this Table module as metatable to a table.
Alias for setmetatable(tbl, {__index = Table}).

Parameters:

Returns:

    table The unchanged input table, now with metatable attached.
NIL
Workaround to put values into tables. Lua can not usually put nil as keys or values in tables because it treats those as not to be in the table in the first place. For situations where you need to put nil values into tables Erlib offers to use this unique string that certain functions like Table.remove_nil, Table.set or Table.patch will recognize as nil value.

Basic Methods

size(tbl)
Counts (key → value) pairs. Uses factorio table_size when available.

Parameters:

Returns:

    NaturalNumber The total number of keys in this table. Counts all types of keys including numeric.
array_size(tbl)
The largest numeric key in the array part of this table. For DenseArrays the length operator # is much faster.

Parameters:

  • tbl MixedTable A table with a sparse array part.

Returns:

    NaturalNumber
range([a=1], b[, step])
Generates a DenseArray of NaturalNumbers.

Parameters:

Returns:

    DenseArray

Usage:

    print(Table.range(10))
    > {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    print(Table.range(5,10))
    > {5, 6, 7, 8, 9, 10}
    print(Table.range(2,44,4))
    > {2, 6, 10, 14, 18, 22, 26, 30, 34, 38, 42}
    
values(tbl)
Generates an unsorted DenseArray from the values of tbl.

Parameters:

Returns:

    DenseArray
keys(tbl)
Generates an unsorted DenseArray from the keys of tbl.

Parameters:

Returns:

    DenseArray
flip(tbl)
Creates a new table in which (key ↔ value) mappings are swapped. Duplicate values will be mapped to the last key that references them but due to the behavior of next it's undefind behavior which key that will be. In factorio pairs is deterministic and it should thus be the key that was added to the table last.

Parameters:

Returns:

    table A new flipped table.

Usage:

    local my_table = {'a','b','c','c'}
    print(Table(my_table):flip():to_string())
    > {a = 1, b = 2, c = 4}
    
    print(Hydra.lines(Table(defines.events):flip()))
    > {
        [0] = "on_tick"
        [1] = "on_gui_click",
        [2] = "on_gui_text_changed",
        [3] = "on_gui_checked_state_changed",
        [4] = "on_entity_died",
        [5] = "on_picked_up_item",
        ...
        }
    
plural(obj)
Wraps the object in a table if it is not already a table.

Parameters:

Returns:

    Table
is_equal(tbl, tbl2)
Deep compare. If two tables have exactly the same content.

Note: Does not compare the content of tables-as-keys.

Parameters:

Returns:

    boolean

Usage:

    local a = {1,2,3,4}
    local b = {5,6,7,8}
    local c = {'a','b','c','d'}; c[5] = c
    local test1 = {a=a,b={b=b,c={c=c}}}
    local test2 = {a=a,b={b=b,c={c=c}}}
    print(test1 == test2)
    > false
    print(Table.is_equal(test1,test2))
    > true
    
is_empty(tbl)
Returns true if the table contains no values.

Parameters:

Returns:

    boolean
nil_if_empty(tbl)
Converts empty tables into a nil value.

Parameters:

Returns:

    table or nil

Search Methods

find_largest(tbl[, gtr])
Finds the largest element in a table.

Parameters:

  • tbl table
  • gtr function A comparitor function f(a,b)→boolean that returns true when a is larger than b. Defaults to a>b. (optional)

Returns:

  1. AnyValue The value.
  2. NotNil The key of the first occurance of value in tbl.
find(tbl, value)
Retrieves the key of a value.

Parameters:

Returns:

    NotNil or nil The key of the first occurance of the value, or nil if value wasn't found.
next_value(tbl[, key=nil])
Fetches the next value in a table. Respects __pairs metamethod. Return value order is reversed compared to lua next. By default will return the first value of a table.

Parameters:

  • tbl table
  • key AnyValue The key preceeding the output key. (default nil)

Returns:

  1. AnyValue The value.
  2. AnyValue The key of above value in tbl.
first_value(tbl)
Shortcut to Table.next_value(tbl,nil) that doesn't return the key at all.

Parameters:

Returns:

    AnyValue The value.

In-Place Methods

pop(tbl, key[, value=nil])
In-place. Removes a (key → value) pair and returns the value. Alternatively replaces the old value with a new value. Does not change the order of the remaining elements.

Parameters:

Returns:

    AnyValue
map(tbl, f[, target=nil])
In-place. Applies a function to all elements of a table.

Experts only: Table.map in Copy Mode supports changing the key that a value is associated with. If f(value,key,tbl) returns two values then the first is the new value and the second is the new key. If it returns one value then the original key will be used. This check is done for each key→value pair seperately.

Parameters:

  • tbl table
  • f function The function f(value,key,tbl) that produces the new value for each key→value mapping in the table.
  • target table Copy Mode. The result of the operation will be written to this table and tbl remains unchanged. (default nil)

Returns:

    table The input table.
filter(tbl, f[, target=nil])
In-place. Removes elements from a table based on a filter function.

Parameters:

  • tbl table
  • f function If calling f(value,key,tbl) does not return truthy then the value will be removed from the table.
  • target table Copy Mode. The result of the operation will be written to this table and tbl remains unchanged. (default nil)

Returns:

    table The input table.
smerge(tbl[, tbl2])
In-place. Shallow Merge. Copies data from one table into another. Copies only the first layer of the table. All sub-table references stay identical.

Parameters:

  • tbl table
  • tbl2 table The table from which to take the data. (optional)

Returns:

    table The input table.
insert_once(tbl, key, value)
In-place. Inserts value into tbl only if no other key in the table has an == equal value.

Parameters:

Returns:

    table The input table.
clear(tbl, except_keys[, is_whitelist=true])
In-place. Removes all key→value mappings from a table.

Parameters:

  • tbl table
  • except_keys DenseArray These keys will not be deleted.
  • is_whitelist boolean If set to false only the except_keys will be deleted. (default true)

Returns:

    table The now empty input table.
overwrite(table_reference, value_table)
In-place. Puts the content of one table into the reference of another. Used when you need to replace all content of a table, but need to keep external references to the table intact.

Parameters:

  • table_reference table All key→value mappings in this table will be deleted.
  • value_table table All key→value mappings will be shallowly copied into table_reference.

Returns:

    Table The input table reference with the

Usage:

    local my_table  = {1,2,3}
    local also_my_table = my_table
    local my_values = {'a','b','c'}
    Table.overwrite(my_table,my_values)
    print(my_table:to_string())
    > {"a", "b", "c"}
    print(my_table == my_values)
    > false
    print(my_table == also_my_table) -- all local references stay intact
    > true
    
migrate(tbl, index, migrations[, ...])
In-place. Applies a series of migration functions to sub-table.

Parameters:

  • tbl table
  • index NotNil The index of the to-be-migrated subtable in tbl. If the index does not yet exist it will be initialized as an empty table.
  • migrations SparseArray A group of to-be-sequentially-applied migration functions. Each function will be called f(tbl[index],index,tbl,...).
  • ... AnyValue Arbitrary extra data that will be passed to each migration function. (optional)

Returns:

    The fully migrated subtable.

Usage:

    local my_data = {
      ['Peter'] = {
        -- No version means _version=0
        name = 'Peter',
        },
      ['Paula'] = {
        -- _version is internally managed and should not be manually changed.
        _version = 1,
        value = 12,
        givenname = 'Paula',
        }
      }
    
    local my_migrations = {
      -- The number indicates that version this function *outputs*
      -- Usually you will only need (data).
      [1] = function(data)
        -- Rename old values.
        data.givenname = data.name
        data.name      = nil
        -- Initialize newly implemented values.
        data.value     = 0
        -- _version can *NOT* be manually changed during a migration.
        data._version  = 42 -- this has no effect
        end,
      -- But sometimes extra parameters are useful.
      [2] = function(data,index,tbl,bonus,superbonus)
        -- Migrations can completely reconstruct the table.
        tbl[index] = {
          gnam = data.givenname or index,
          val  = data.value + bonus + (superbonus or 0)
          }
        end,
      }
    
    -- You can migrate old data.
    for k,_ in pairs(my_data) do
      Table.migrate(my_data,k,my_migrations,30)
      print(k,':',Table(my_data[k]):to_string())
      end
    > Paula : {_version = 2, gnam = "Paula", val = 42}
    > Peter : {_version = 2, gnam = "Peter", val = 30}
    
    -- Or you can create new data.
    Table.migrate(my_data,'Alex',my_migrations,1,9000) -- with superbonus
    print('Alex :',Table(my_data['Alex']):to_string())
    > Alex  : {_version = 2, gnam = "Alex", val = 9001}
    

Copy Methods

scopy(tbl)
Shallow Copy. Copies the first level of the table such that all sub-table references stay identical to the original table.

Parameters:

Returns:

    table The new table.
dcopy(tbl[, remove_metatables=false])
Deep Copy. A copy of a table that shares none of the original table references but has the same self-referencing structure.

Parameters:

  • tbl AnyValue
  • remove_metatables boolean Removes metatables from tbl and all sub-tables. (default false)

Returns:

    table The new table.
fcopy(tbl[, remove_metatables=false])
Full Copy. A copy of a table that shares none of the original table references and in which all formerly self-referenced sub-tables are made unique. Mostly useful for visual inspection of complex tables.

Parameters:

  • tbl AnyValue
  • remove_metatables boolean Removes metatables from tbl and all sub-tables. (default false)

Returns:

    table The new table.

Other Methods

rep(tbl[, variation_count[, patterns]])
Creates patterned and unpatterened table repetitions. Either count or patterns or both must be given.

Parameters:

  • tbl table
  • variation_count NaturalNumber How many repetitions to create. Will use the length of the first patterned key if not given. (optional)
  • patterns table A table that maps each key to a DenseArray of at least length variation_count. (optional)

Returns:

    table

Usage:

  • -- Simple example. Patternless repetition.
    local test = Table.rep({1,2,3},3)
    print(Hydra.lines(test))
    > {
    >   {1, 2, 3},
    >   {1, 2, 3},
    >   {1, 2, 3}
    > }
    
  • -- Intermediate example. Patterned repetition.
    local test = Table.rep({},3,{name = {'Peter','Paula','Alex'}})
    print(Hydra.lines(test))
    > {
    >   {name = "Peter"},
    >   {name = "Paula"},
    >   {name = "Alex"}
    > }
    
  • -- Advanced example.
    -- Creating a Gui.construct compatible layout for a simple calculator.
    
    local buttons = {
      1 , 2 , 3 ,'+','-',
      4 , 5 , 6 ,'*','/',
      7 , 8 , 9 ,'(',')',
      0 ,'.','←','C',
      }
    
    local layout = Table.rep(
      {'button'},
      nil, -- You can automatically use #buttons length derived from #caption.
      {
        caption=buttons,
        path = Table.rep( -- Nested call first creates a variation table.
          {'buttons'},
          #buttons, -- Or you can specify the length manually.
          {[2]=buttons}
          )
        }
      )
    
    print(Hydra.lines(layout))
    > {
        {"button", caption =  1 , path = {"buttons",  1 }},
        {"button", caption =  2 , path = {"buttons",  2 }},
        {"button", caption =  3 , path = {"buttons",  3 }},
        {"button", caption = "+", path = {"buttons", "+"}},
        {"button", caption = "-", path = {"buttons", "-"}},
        {"button", caption =  4 , path = {"buttons",  4 }},
        {"button", caption =  5 , path = {"buttons",  5 }},
        {"button", caption =  6 , path = {"buttons",  6 }},
        {"button", caption = "*", path = {"buttons", "*"}},
        {"button", caption = "/", path = {"buttons", "/"}},
        {"button", caption =  7 , path = {"buttons",  7 }},
        {"button", caption =  8 , path = {"buttons",  8 }},
        {"button", caption =  9 , path = {"buttons",  9 }},
        {"button", caption = "(", path = {"buttons", "("}},
        {"button", caption = ")", path = {"buttons", ")"}},
        {"button", caption =  0 , path = {"buttons",  0 }},
        {"button", caption = ".", path = {"buttons", "."}},
        {"button", caption = "←", path = {"buttons", "←"}},
        {"button", caption = "C", path = {"buttons", "C"}}
      }
    
remove_nil(tbl)
In-place. Shallowly replaces Table.NIL keys and values with nil, deleting the affected mappings.

Parameters:

Returns:

    tbl

Conversion

to_array(tbl[, target=nil])
In-place. Converts MixedTable to SparseArray. All keys that are not NaturalNumbers will be removed.

Parameters:

  • tbl table
  • target table Copy Mode. This table will be changed and tbl remains unchanged. (default nil)

Returns:

    SparseArray or DenseArray A table containing only the numeric keys of the input array.
to_string(tbl)
Alias of String.to_string.

Parameters:

Returns:

    string

Metamethods

__concat()
Addition with + is Table.smerge().
set_metamethod(tbl, method_name, f)
Set a function as metamethod of tbl. Inherits current metatable or creates a new one. Will overwrite existing metamethods of the same name.

Parameters:

Returns:

    table This does not automatically inherit any methods of this Table module.
get_metamethod(tbl, method_name)
Gets the metamethod handler function of tbl.

Parameters:

  • tbl table
  • method_name string "index", "newindex", etc.

Returns:

    function
deep_clear_metatables(tbl)
Recursively removes metatables from all subtables but not from other object types.

Parameters:

Returns:

    table The input table. Doesn't have a Table module metatable.

Usage:

    local test = setmetatable({},{
      __index = function() print'first meta' return 1 end,
      })
    -- recursive
    test.test = test
    -- different
    test.foo  = setmetatable({},{
      __index = function() print'second meta' return 2 end,
      })
    
    -- metamethods will trigger additional printing
    local x = test[1]
    > first meta
    local x = test.test[1]
    > first meta
    local x = test.foo[1]
    > second meta
    
    Table.deep_clear_metatables(test)
    
    -- without metatables there is no printing (and also no values in this case).
    local x = test[1]
    local x = test.test[1]
    local x = test.foo[1]
    
clear_meta(tbl)
Removes any metatable from a table. Does not recurse into the table.

Parameters:

Returns:

    table The input table. Without any metatable whatsoever.
popmetatable(tbl)
Removes and returns the metatable. Useful for temporarily removing and later reinstating the metatable.

Parameters:

Returns:

    nil or table The metatable.

Path Methods

TablePath
Concept. A DenseArray of values that represent keys of a nested path in another table.
get(tbl, path[, default=nil])
Get the value at location path in tbl.

Parameters:

  • tbl table
  • path table
  • default AnyValue The value that will be returned if the full path points at a nil value or if the path only partially exists in tbl. (default nil)

Returns:

    NotNil or nil

Usage:

  • local tbl = {a = {b = {c = 42}}}
    local path = {'a','b','c'}
    print (Table(tbl):get(path))
    > 42
    
  • local tbl = {a = {b = {c = 42}}}
    local path = {'a','b','c','d','e'}
    print (Table.get(tbl,path,"Don't panic!"))
    > Don't panic!
    
set(tbl, path, value)
Set a new value to location path in tbl. Automatically creates subtables nessecary to fullfill the path.

Parameters:

Returns:

    value A reference to the input value given.
sget(tbl, path, default)
Get the value at location path in tbl if it exists, otherwise creates it. Automatically creates subtables nessecary to fullfill the path.

Parameters:

Returns:

    AnyValue A reference to the found value or the default value.
add(tbl, path, number)
Adds a number to an existing value or creates a new value.

Alias: Table['+='](t,p,n)

Parameters:

remove(tbl, path)
Removes and returns a value from a table.

Does not remove empty sub-tables left behind after removing all keys.

Note: Not to be confused with table.remove which only works on arrays.

Parameters:

Returns:

    AnyValue
TablePatch
Concept. A DenseArray consisting of a TablePath followed by a TablePatchValue.
TablePatchValue
Concept.
The value part of a TablePatch is not further interpreted unless it is a MixedTable made of a TablePath that contains the mapping {self=true}. In this case the actual value will be fetched from the table being patched. Mainly used for in-line self refernces during data-stage prototype creation.

Fields:

  • self boolean Unless this is true the whole table is the value. (default nil)
  • copy boolean By default self-referencing values will be copied. Set this to false if you want to use a direct reference instead. (default true)
patch(tbl, patches)
Takes an array of patches and applies them to a table.

Parameters:

Returns:

    table The input table.

Usage:

    local test = {one = 1}
    Table(test)
      :patch({{'two',value=2}})
    test:patch({
      {'deeper','one',value={self=true,copy=true,'one'}},
      {'deeper','two',value={self=true,copy=true,'two'}},
      })
    print(Hydra.line(test))
    > {deeper = {one = 1, two = 2}, one = 1, two = 2}
    

Factories

normalizer(defaults)
Factory. Applies default values to tables.

Parameters:

  • defaults table Mappings key→default_value.

Returns:

    function TableNormalizerFunction
TableNormalizerFunction(tbl)
In-place. Applies enclosurized defaults.

Parameters:

Returns:

    Table The input table.

Usage:

    local my_norm = Table.normalizer{name='no name',value=0}
    print(my_norm{name='testrr'}:to_string())
    > {name = "testrr", value = 0}
    
    
remapper(mappings[, allow_tables_as_keys=false])
Factory. Moves values from one key to another.

Parameters:

  • mappings table Mappings old_key→new_key or old_key→{new_key_1,...,new_key_n}
  • allow_tables_as_keys boolean When this is true then new_key of type table will not be interpreted as a DenseArray of new keys but instead used directly as the key. (default false)

Returns:

    function TableRemapperFunction
TableRemapperFunction(tbl)
In-place. Applies enclosurized re-mappings.

Parameters:

Returns:

    Table The input table.

Usage:

    -- with multiple remappings per key
    local my_remapper1 = Table.remapper {name='surname',value={'cur','act'}}
    local test_person1 = {name='Adicator',value=42}
    print(my_remapper1(test_person1):to_string())
    > {act = 42, cur = 42, surname = "Adicator"}
    
    -- with tables as keys
    local my_remapper2 = Table.remapper({name='surname',value={'cur','act'}},true)
    local test_person2 = {name='Bdicator',value=42}
    print(my_remapper2(test_person2):to_string())
    > {[{"cur","act"}] = 42, surname = "Bdicator"}
    
generated by LDoc 1.4.6 Last updated 2021-09-10 19:51:19