From f9cb4f3dda0286a3a41ca09fe6b797330b7a3160 Mon Sep 17 00:00:00 2001 From: LordMidas <55047920+LordMidas@users.noreply.github.com> Date: Sat, 31 Dec 2022 00:05:29 -0500 Subject: [PATCH 1/3] feat: add set class which is an unordered collection of uniques --- msu/classes/set.nut | 100 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 msu/classes/set.nut diff --git a/msu/classes/set.nut b/msu/classes/set.nut new file mode 100644 index 000000000..a57208c63 --- /dev/null +++ b/msu/classes/set.nut @@ -0,0 +1,100 @@ +::MSU.Class.Set <- class +{ + Table = null; + Array = null; + + constructor( _table = null ) + { + if (_table != null) + { + ::MSU.requireTable(_table); + foreach (key, value in _table) + { + this.Table[key] <- null; + this.Array.push(key); + } + } + } + + function _get( _idx ) + { + if (_idx == "weakref") throw null; + return this.Array[_idx]; + } + + function _cloned( _original ) + { + this.Table = clone _original.Table; + this.Array = clone _original.Array; + } + + function _nexti( _prev ) + { + _prev = _prev == null ? 0 : _prev + 1; + return _prev == this.Array.len() ? null : _prev; + } + + function add( _item ) + { + if (_item in this.Table) throw ::MSU.Exception.DuplicateKey(_item); + this.Table[_item] <- null; + this.Array.push(_item); + } + + function remove( _item ) + { + if (!(_item in this.Table)) throw ::MSU.Exception.KeyNotFound(_item); + delete this.Table[_item]; + this.Array.remove(this.Array.find(_item)); + } + + function contains( _item ) + { + return _item in this.Table; + } + + function toArray() + { + return clone this.Array; + } + + function apply( _function ) + { + // _function ( _item ) + // must return value that will replace _item in this set + + foreach (i, item in this.Array) + { + delete this.Table[item]; + local newVal = _function(item); + this.Array[i] = newVal; + this.Table[newVal] <- null; + } + } + + function map( _function ) + { + // _function ( _item ) + // must return value that will be stored in the returned set instead of _item + + local ret = ::MSU.Class.Set(); + foreach (item in this.Array) + { + ret.add(_function(item)) + } + return ret; + } + + function filter( _function ) + { + // _function ( _item ) + // must return a boolean, if false then _item is not added to the returned set + + local ret = ::MSU.Class.Set(); + foreach (item in this.Array) + { + if (_function(item)) ret.add(item); + } + return ret; + } +} From 2f82dba1bc1d35f32603deefcf6947af63575aa6 Mon Sep 17 00:00:00 2001 From: LordMidas <55047920+LordMidas@users.noreply.github.com> Date: Sat, 4 May 2024 11:51:40 -0400 Subject: [PATCH 2/3] refactor: clean up the class by using only table internally --- msu/classes/set.nut | 69 ++++++++++++++++++++++----------------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/msu/classes/set.nut b/msu/classes/set.nut index a57208c63..1a27a53c4 100644 --- a/msu/classes/set.nut +++ b/msu/classes/set.nut @@ -1,51 +1,56 @@ ::MSU.Class.Set <- class { - Table = null; - Array = null; + Table = null; // Cannot contain null - constructor( _table = null ) + constructor( _tableOrArray = null ) { - if (_table != null) + this.Table = {}; + if (_tableOrArray != null) { - ::MSU.requireTable(_table); - foreach (key, value in _table) + switch (typeof _tableOrArray) { - this.Table[key] <- null; - this.Array.push(key); + case "table": + foreach (key, _ in _tableOrArray) + this.add(key); + break; + + case "array": + foreach (item in _tableOrArray) + this.add(item); + break; + + default: + throw ::MSU.Exception.InvalidType(_tableOrArray); } } } - function _get( _idx ) - { - if (_idx == "weakref") throw null; - return this.Array[_idx]; - } - function _cloned( _original ) { this.Table = clone _original.Table; - this.Array = clone _original.Array; } - function _nexti( _prev ) + // Used for iterating over the set e.g. foreach (item in mySet.toArray()) + // We don't implement _nexti because of two reasons: + // - It is orders of magnitude slower than iterating on a table + // - It is not compatible with nested foreach loops where you have a "break" in the nested loop + function toArray() { - _prev = _prev == null ? 0 : _prev + 1; - return _prev == this.Array.len() ? null : _prev; + return ::MSU.Table.keys(this.Table); } function add( _item ) { - if (_item in this.Table) throw ::MSU.Exception.DuplicateKey(_item); - this.Table[_item] <- null; - this.Array.push(_item); + if (_item in this.Table) + throw ::MSU.Exception.DuplicateKey(_item); + this.Table[_item] <- false; } function remove( _item ) { - if (!(_item in this.Table)) throw ::MSU.Exception.KeyNotFound(_item); + if (!(_item in this.Table)) + throw ::MSU.Exception.KeyNotFound(_item); delete this.Table[_item]; - this.Array.remove(this.Array.find(_item)); } function contains( _item ) @@ -53,23 +58,17 @@ return _item in this.Table; } - function toArray() - { - return clone this.Array; - } - function apply( _function ) { // _function ( _item ) // must return value that will replace _item in this set - foreach (i, item in this.Array) + local newTable = {}; + foreach (item, _ in this.Table) { - delete this.Table[item]; - local newVal = _function(item); - this.Array[i] = newVal; - this.Table[newVal] <- null; + newTable[_function(item)] <- false; } + this.Table = newTable; } function map( _function ) @@ -78,7 +77,7 @@ // must return value that will be stored in the returned set instead of _item local ret = ::MSU.Class.Set(); - foreach (item in this.Array) + foreach (item, _ in this.Table) { ret.add(_function(item)) } @@ -91,7 +90,7 @@ // must return a boolean, if false then _item is not added to the returned set local ret = ::MSU.Class.Set(); - foreach (item in this.Array) + foreach (item, _ in this.Table) { if (_function(item)) ret.add(item); } From 5cf9b37d15b243552b67d5b86f004a6137c3d033 Mon Sep 17 00:00:00 2001 From: LordMidas <55047920+LordMidas@users.noreply.github.com> Date: Sat, 4 May 2024 11:52:52 -0400 Subject: [PATCH 3/3] refactor: don't throw when adding duplicate --- msu/classes/set.nut | 2 -- 1 file changed, 2 deletions(-) diff --git a/msu/classes/set.nut b/msu/classes/set.nut index 1a27a53c4..166da63f7 100644 --- a/msu/classes/set.nut +++ b/msu/classes/set.nut @@ -41,8 +41,6 @@ function add( _item ) { - if (_item in this.Table) - throw ::MSU.Exception.DuplicateKey(_item); this.Table[_item] <- false; }