mirror of
https://github.com/1bardesign/batteries.git
synced 2024-11-22 14:14:36 +00:00
[added] set module with full (-ish?) suite of set operations and efficient (non-linear) membership testing
closes #4
This commit is contained in:
parent
28e06c4a10
commit
e5be0df492
27
init.lua
27
init.lua
@ -1,22 +1,7 @@
|
||||
--[[
|
||||
batteries for lua
|
||||
|
||||
if required as the "entire library" (ie by this file), puts everything into
|
||||
global namespace by default as it'll presumably be commonly used
|
||||
|
||||
if not, several of the modules work as normal lua modules and return a table
|
||||
for local-friendly use
|
||||
|
||||
the others that modify some global table can be talked into behaving as normal
|
||||
lua modules as well by setting appropriate globals prior to inclusion
|
||||
|
||||
you can avoid modifying any global namespace by setting
|
||||
|
||||
BATTERIES_NO_GLOBALS = true
|
||||
|
||||
before requiring, then everything can be accessed as eg
|
||||
|
||||
batteries.table.stable_sort
|
||||
a collection of helpful code to get your project off the ground faster
|
||||
]]
|
||||
|
||||
local path = ...
|
||||
@ -32,7 +17,9 @@ local _tablex = require_relative("tablex")
|
||||
local _stable_sort = require_relative("stable_sort")
|
||||
|
||||
local _functional = require_relative("functional")
|
||||
|
||||
local _sequence = require_relative("sequence")
|
||||
local _set = require_relative("set")
|
||||
|
||||
local _stringx = require_relative("stringx")
|
||||
|
||||
@ -69,8 +56,9 @@ local _batteries = {
|
||||
sort = _stable_sort,
|
||||
--
|
||||
functional = _functional,
|
||||
--
|
||||
--collections
|
||||
sequence = _sequence,
|
||||
set = _set,
|
||||
--geom
|
||||
vec2 = _vec2,
|
||||
vec3 = _vec3,
|
||||
@ -97,8 +85,9 @@ function _batteries:export(self)
|
||||
--functional module also available separate from table
|
||||
functional = _functional
|
||||
|
||||
--export sequence
|
||||
--export collections
|
||||
sequence = _sequence
|
||||
set = _set
|
||||
|
||||
--overlay onto math
|
||||
_tablex.overlay(math, _mathx)
|
||||
@ -111,7 +100,7 @@ function _batteries:export(self)
|
||||
vec3 = _vec3
|
||||
intersect = _intersect
|
||||
|
||||
--misc :)
|
||||
--"misc" :)
|
||||
unique_mapping = _unique_mapping
|
||||
state_machine = _state_machine
|
||||
async = _async
|
||||
|
138
set.lua
Normal file
138
set.lua
Normal file
@ -0,0 +1,138 @@
|
||||
--[[
|
||||
set type with appropriate operations
|
||||
]]
|
||||
|
||||
local path = (...):gsub("set", "")
|
||||
local class = require(path .. "class")
|
||||
local table = require(path .. "tablex") --shadow global table module
|
||||
|
||||
local set = class()
|
||||
|
||||
--construct a new set
|
||||
--elements is an optional ordered table of elements to be added to the set
|
||||
function set:new(elements)
|
||||
self = self:init({
|
||||
_keyed = {},
|
||||
_ordered = {},
|
||||
})
|
||||
if elements then
|
||||
for _, v in ipairs(elements) do
|
||||
self:add(v)
|
||||
end
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--check if an element is present in the set
|
||||
function set:has(v)
|
||||
return self._keyed[v] or false
|
||||
end
|
||||
|
||||
--add a value to the set, if it's not already present
|
||||
function set:add(v)
|
||||
if not self:has(v) then
|
||||
self._keyed[v] = true
|
||||
table.insert(self._ordered, v)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--remove a value from the set, if it's present
|
||||
function set:remove(v)
|
||||
if self:has(v) then
|
||||
self._keyed[v] = nil
|
||||
table.remove_value(self._ordered, v)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--iterate the values in the set, along with their index
|
||||
--the index is useless but harmless, and adding a custom iterator seems
|
||||
--like a really easy way to encourage people to use slower-than-optimal code
|
||||
function set:ipairs()
|
||||
return ipairs(self._ordered)
|
||||
end
|
||||
|
||||
--get a copy of the values in the set, as a simple table
|
||||
function set:values()
|
||||
return table.copy(self._ordered)
|
||||
end
|
||||
|
||||
--modifying operations
|
||||
|
||||
--add all the elements present in the other set
|
||||
function set:add_set(other)
|
||||
for i, v in other:ipairs() do
|
||||
self:add(v)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--remove all the elements present in the other set
|
||||
function set:subtract_set(other)
|
||||
for i, v in other:ipairs() do
|
||||
self:remove(v)
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
--new collection operations
|
||||
|
||||
--copy a set
|
||||
function set:copy()
|
||||
return set:new():add_set(self)
|
||||
end
|
||||
|
||||
--create a new set containing the complement of the other set contained in this one
|
||||
--the elements present in this set but not present in the other set will remain in the result
|
||||
function set:complement(other)
|
||||
return self:copy():subtract_set(other)
|
||||
end
|
||||
|
||||
--alias
|
||||
set.difference = set.complement
|
||||
|
||||
--create a new set containing the union of this set with another
|
||||
--an element present in either set will be present in the result
|
||||
function set:union(other)
|
||||
return self:copy():add_set(other)
|
||||
end
|
||||
|
||||
--create a new set containing the intersection of this set with another
|
||||
--only the elements present in both sets will remain in the result
|
||||
function set:intersection(other)
|
||||
local r = set:new()
|
||||
for i, v in self:ipairs() do
|
||||
if other:has(v) then
|
||||
r:add(v)
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
--create a new set containing the symmetric difference of this set with another
|
||||
--only the elements not present in both sets will remain in the result
|
||||
--similiar to a logical XOR operation
|
||||
--
|
||||
--equal to self:union(other):subtract_set(self:intersection(other))
|
||||
-- but with much less wasted effort
|
||||
function set:symmetric_difference(other)
|
||||
local r = set:new()
|
||||
for i, v in self:ipairs() do
|
||||
if not other:has(v) then
|
||||
r:add(v)
|
||||
end
|
||||
end
|
||||
for i, v in other:ipairs() do
|
||||
if not self:has(v) then
|
||||
r:add(v)
|
||||
end
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
--alias
|
||||
set.xor = set.symmetric_difference
|
||||
|
||||
--
|
||||
return set
|
Loading…
Reference in New Issue
Block a user