collect-your-stuff 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/LICENSE +674 -0
  2. package/README.md +1676 -0
  3. package/browser/collect-your-stuff.js +18987 -0
  4. package/browser/collect-your-stuff.min.js +1 -0
  5. package/dist/collections/arrayable/ArrayElement.js +95 -0
  6. package/dist/collections/arrayable/ArrayElement.min.js +1 -0
  7. package/dist/collections/arrayable/Arrayable.js +253 -0
  8. package/dist/collections/arrayable/Arrayable.min.js +1 -0
  9. package/dist/collections/doubly-linked-llist/DoubleLinker.js +90 -0
  10. package/dist/collections/doubly-linked-llist/DoubleLinker.min.js +1 -0
  11. package/dist/collections/doubly-linked-llist/DoublyLinkedList.js +234 -0
  12. package/dist/collections/doubly-linked-llist/DoublyLinkedList.min.js +1 -0
  13. package/dist/collections/linked-list/LinkedList.js +256 -0
  14. package/dist/collections/linked-list/LinkedList.min.js +1 -0
  15. package/dist/collections/linked-list/Linker.js +100 -0
  16. package/dist/collections/linked-list/Linker.min.js +1 -0
  17. package/dist/collections/linked-tree-list/LinkedTreeList.js +96 -0
  18. package/dist/collections/linked-tree-list/LinkedTreeList.min.js +1 -0
  19. package/dist/collections/linked-tree-list/TreeLinker.js +112 -0
  20. package/dist/collections/linked-tree-list/TreeLinker.min.js +1 -0
  21. package/dist/collections/queue/Queue.js +163 -0
  22. package/dist/collections/queue/Queue.min.js +1 -0
  23. package/dist/collections/queue/Queueable.js +177 -0
  24. package/dist/collections/queue/Queueable.min.js +1 -0
  25. package/dist/collections/stack/Stack.js +141 -0
  26. package/dist/collections/stack/Stack.min.js +1 -0
  27. package/dist/collections/stack/Stackable.js +85 -0
  28. package/dist/collections/stack/Stackable.min.js +1 -0
  29. package/dist/main.js +44 -0
  30. package/dist/main.min.js +1 -0
  31. package/dist/recipes/Runnable.js +67 -0
  32. package/dist/recipes/Runnable.min.js +1 -0
  33. package/dist/recipes/recipes.js +23 -0
  34. package/dist/recipes/recipes.min.js +1 -0
  35. package/package.json +44 -0
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ require("core-js/modules/esnext.async-iterator.reduce.js");
8
+ require("core-js/modules/esnext.iterator.constructor.js");
9
+ require("core-js/modules/esnext.iterator.reduce.js");
10
+ /**
11
+ * @file linked list item.
12
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
13
+ * @version 1.0.0
14
+ * @memberOf module:collect-your-stuff
15
+ */
16
+
17
+ /**
18
+ * Element represents a node in an Arrayable.
19
+ */
20
+ class ArrayElement {
21
+ data = null;
22
+ classType;
23
+
24
+ /**
25
+ * Create the new Element instance, provide the data and optionally configure the type of Element.
26
+ * @param {*} [data=null]
27
+ * @param {ArrayElement} [elementClass=Element]
28
+ */
29
+ constructor() {
30
+ let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
31
+ let elementClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ArrayElement;
32
+ this.classType = elementClass;
33
+ this.data = data;
34
+ }
35
+
36
+ /**
37
+ * Return the type of class used for Element.
38
+
39
+ * @return {ArrayElement}
40
+ */
41
+ get classType() {
42
+ return this.classType;
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Make a new Element from the data given if it is not already a valid Element.
48
+ * @methodof ArrayElement
49
+ * @param {ArrayElement|*} element
50
+ * @param {ArrayElement} [elementClass=Element]
51
+ * @return {ArrayElement}
52
+ */
53
+ ArrayElement.make = function (element) {
54
+ let elementClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ArrayElement;
55
+ if (typeof element !== 'object') {
56
+ // It is not an object, so instantiate the Element with element as the data
57
+ return new elementClass(element);
58
+ }
59
+ if (element.classType) {
60
+ // Already valid Element, return as-is
61
+ return element;
62
+ }
63
+ // Create the new node as the configured #classType
64
+ return new elementClass(element, elementClass);
65
+ };
66
+
67
+ /**
68
+ * Convert an array into Element instances, return the head and tail Elements.
69
+ * @methodof ArrayElement
70
+ * @param {Array} [values=[]]
71
+ * @param {ArrayElement} [elementClass=Element]
72
+ * @returns {{head: ArrayElement, tail: ArrayElement}}
73
+ */
74
+ ArrayElement.fromArray = function () {
75
+ let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
76
+ let elementClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ArrayElement;
77
+ return values.reduce((references, element) => {
78
+ const newElement = elementClass.make(element);
79
+ if (!references.head.length) {
80
+ // Initialize the head and tail with the new node
81
+ return {
82
+ head: [newElement],
83
+ tail: newElement
84
+ };
85
+ }
86
+ // Only update the tail once head has been set, tail is always the most recent node
87
+ references.head.push(newElement);
88
+ references.tail = newElement;
89
+ return references;
90
+ }, {
91
+ head: [],
92
+ tail: null
93
+ });
94
+ };
95
+ var _default = exports.default = ArrayElement;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0,require("core-js/modules/esnext.async-iterator.reduce.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js");class ArrayElement{data=null;classType;constructor(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:null,t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ArrayElement;this.classType=t,this.data=e}get classType(){return this.classType}}ArrayElement.make=function(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ArrayElement;return"object"!=typeof e?new t(e):e.classType?e:new t(e,t)},ArrayElement.fromArray=function(){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:ArrayElement;return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:[]).reduce(((t,r)=>{const l=e.make(r);return t.head.length?(t.head.push(l),t.tail=l,t):{head:[l],tail:l}}),{head:[],tail:null})};var _default=exports.default=ArrayElement;
@@ -0,0 +1,253 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ArrayElement = _interopRequireDefault(require("./ArrayElement"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ /**
10
+ * @file doubly linked list.
11
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
12
+ * @version 1.0.0
13
+ * @memberOf module:collect-your-stuff
14
+ */
15
+
16
+ /**
17
+ * DoublyLinkedList represents a collection stored as a LinkedList with prev and next references.
18
+ */
19
+ class Arrayable {
20
+ classType = null;
21
+ initialized = false;
22
+ innerList = [];
23
+
24
+ /**
25
+ * Create the new Arrayable instance, configure the Arrayable class.
26
+ * @param {Arrayable|Iterable} classType
27
+ */
28
+ constructor() {
29
+ let classType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Arrayable;
30
+ this.classType = classType;
31
+ this.initialized = false;
32
+ }
33
+
34
+ /**
35
+ * Initialize the inner list, should only run once.
36
+ * @method
37
+ * @param {ArrayElement|Array} initialList
38
+ * @return {Arrayable}
39
+ */
40
+ initialize(initialList) {
41
+ if (this.initialized) {
42
+ console.warn('Attempt to initialize Arrayable which is not empty.');
43
+ return this;
44
+ }
45
+ this.initialized = true;
46
+ this.innerList = initialList;
47
+ return this;
48
+ }
49
+
50
+ /**
51
+ * Return the type of class used for Arrayable.
52
+
53
+ * @returns {Arrayable}
54
+ */
55
+ get classType() {
56
+ return this.classType;
57
+ }
58
+
59
+ /**
60
+ * Detect if the inner list has been initialized.
61
+
62
+ * @returns {boolean}
63
+ */
64
+ get initialized() {
65
+ return this.initialized;
66
+ }
67
+
68
+ /**
69
+ * Retrieve a copy of the innerList used.
70
+
71
+ * @returns {Array}
72
+ */
73
+ get innerList() {
74
+ return this.innerList;
75
+ }
76
+
77
+ /**
78
+ * Retrieve the first Element from the Arrayable
79
+
80
+ * @returns {ArrayElement}
81
+ */
82
+ get first() {
83
+ return this.innerList[0];
84
+ }
85
+
86
+ /**
87
+ * Retrieve the last Element from the Arrayable
88
+
89
+ * @returns {ArrayElement}
90
+ */
91
+ get last() {
92
+ return this.innerList[this.length - 1];
93
+ }
94
+
95
+ /**
96
+ * Return the length of the list.
97
+
98
+ * @returns {number}
99
+ */
100
+ get length() {
101
+ return this.innerList.length;
102
+ }
103
+
104
+ /**
105
+ * Insert a new node (or data) after a node.
106
+ * @method
107
+ * @param {ArrayElement|*} node
108
+ * @param {ArrayElement|*} newNode
109
+ * @returns {Arrayable}
110
+ */
111
+ insertAfter(node, newNode) {
112
+ const insertAt = this.innerList.indexOf(node);
113
+ this.innerList.splice(insertAt + 1, 0, node.classType.make(newNode));
114
+ return this;
115
+ }
116
+
117
+ /**
118
+ * Insert a new node (or data) before a node.
119
+ * @method
120
+ * @param {ArrayElement|*} node
121
+ * @param {ArrayElement|*} newNode
122
+ * @returns {Arrayable}
123
+ */
124
+ insertBefore(node, newNode) {
125
+ const insertAt = this.innerList.indexOf(node);
126
+ this.innerList.splice(insertAt, 0, node.classType.make(newNode));
127
+ return this;
128
+ }
129
+
130
+ /**
131
+ * Add a node (or data) after the given (or last) node in the list.
132
+ * @method
133
+ * @param {ArrayElement|*} node
134
+ * @param {ArrayElement} after
135
+ * @returns {Arrayable}
136
+ */
137
+ append(node) {
138
+ let after = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.last;
139
+ this.insertAfter(after, node);
140
+ return this;
141
+ }
142
+
143
+ /**
144
+ * Add a node (or data) before the given (or first) node in the list.
145
+ * @method
146
+ * @param {ArrayElement|*} node
147
+ * @param {ArrayElement} before
148
+ * @returns {Arrayable}
149
+ */
150
+ prepend(node) {
151
+ let before = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.first;
152
+ this.insertBefore(before, node);
153
+ return this;
154
+ }
155
+
156
+ /**
157
+ * Remove an element from this arrayable.
158
+ * @method
159
+ * @param {ArrayElement} node
160
+ * @return {ArrayElement}
161
+ */
162
+ remove(node) {
163
+ const deleteAt = this.innerList.indexOf(node);
164
+ this.innerList.splice(deleteAt, 1);
165
+ return node;
166
+ }
167
+
168
+ /**
169
+ * Retrieve a DoubleLinker item from this list by numeric index, otherwise return null.
170
+ * @method
171
+ * @param {number} index
172
+ * @return {ArrayElement|null}
173
+ */
174
+ item(index) {
175
+ if (index >= this.innerList.length) {
176
+ // index is beyond array limit
177
+ return null;
178
+ }
179
+ if (index >= 0) {
180
+ // use the positive index at nth position from the beginning of the array
181
+ return this.innerList[index];
182
+ }
183
+ const calculatedIndex = this.length + index;
184
+ if (calculatedIndex < 0) {
185
+ // negative index is beyond array limit (minus direction)
186
+ return null;
187
+ }
188
+ // Return the item at nth position from the end of the array
189
+ return this.innerList[calculatedIndex];
190
+ }
191
+
192
+ /**
193
+ * Run this function for each element in this arrayable.
194
+ * @callback forEachCallback
195
+ * @param {ArrayElement} element
196
+ * @param {number} index
197
+ * @param {Arrayable} thisArg
198
+ * @returns void
199
+ */
200
+
201
+ /**
202
+ * Be able to run forEach on this Arrayable to iterate over the elements.
203
+ * @param {forEachCallback} callback
204
+ * @param {Arrayable} thisArg
205
+ * @returns {Arrayable}
206
+ */
207
+ forEach(callback) {
208
+ let thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this;
209
+ for (let i = 0; i < thisArg.length; ++i) {
210
+ callback(thisArg.item(i), i, thisArg);
211
+ }
212
+ return thisArg;
213
+ }
214
+
215
+ /**
216
+ * Be able to iterate over this class.
217
+ * @method
218
+ * @returns {Iterator}
219
+ */
220
+ [Symbol.iterator]() {
221
+ let index = 0;
222
+ return {
223
+ next: () => {
224
+ if (index < this.innerList.length) {
225
+ return {
226
+ value: this.innerList[index++],
227
+ done: false
228
+ };
229
+ }
230
+ return {
231
+ done: true
232
+ };
233
+ }
234
+ };
235
+ }
236
+ }
237
+
238
+ /**
239
+ * Convert an array to an Arrayable.
240
+ * @methodof Arrayable
241
+ * @param {Array} values
242
+ * @param {ArrayElement} elementClass
243
+ * @param {Arrayable|Iterable} classType
244
+ * @returns {Arrayable}
245
+ */
246
+ Arrayable.fromArray = function () {
247
+ let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
248
+ let elementClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _ArrayElement.default;
249
+ let classType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : Arrayable;
250
+ const list = new classType(elementClass);
251
+ return list.initialize(elementClass.fromArray(values, elementClass).head);
252
+ };
253
+ var _default = exports.default = Arrayable;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _ArrayElement=_interopRequireDefault(require("./ArrayElement"));function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}class Arrayable{classType=null;initialized=!1;innerList=[];constructor(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:Arrayable;this.classType=t,this.initialized=!1}initialize(t){return this.initialized?(console.warn("Attempt to initialize Arrayable which is not empty."),this):(this.initialized=!0,this.innerList=t,this)}get classType(){return this.classType}get initialized(){return this.initialized}get innerList(){return this.innerList}get first(){return this.innerList[0]}get last(){return this.innerList[this.length-1]}get length(){return this.innerList.length}insertAfter(t,e){const i=this.innerList.indexOf(t);return this.innerList.splice(i+1,0,t.classType.make(e)),this}insertBefore(t,e){const i=this.innerList.indexOf(t);return this.innerList.splice(i,0,t.classType.make(e)),this}append(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.last;return this.insertAfter(e,t),this}prepend(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this.first;return this.insertBefore(e,t),this}remove(t){const e=this.innerList.indexOf(t);return this.innerList.splice(e,1),t}item(t){if(t>=this.innerList.length)return null;if(t>=0)return this.innerList[t];const e=this.length+t;return e<0?null:this.innerList[e]}forEach(t){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this;for(let i=0;i<e.length;++i)t(e.item(i),i,e);return e}[Symbol.iterator](){let t=0;return{next:()=>t<this.innerList.length?{value:this.innerList[t++],done:!1}:{done:!0}}}}Arrayable.fromArray=function(){let t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:_ArrayElement.default;return new(arguments.length>2&&void 0!==arguments[2]?arguments[2]:Arrayable)(e).initialize(e.fromArray(t,e).head)};var _default=exports.default=Arrayable;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ require("core-js/modules/esnext.async-iterator.reduce.js");
8
+ require("core-js/modules/esnext.iterator.constructor.js");
9
+ require("core-js/modules/esnext.iterator.reduce.js");
10
+ var _Linker = _interopRequireDefault(require("../linked-list/Linker"));
11
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
+ /**
13
+ * @file doubly linked list item.
14
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
15
+ * @version 1.0.0
16
+ * @memberOf module:collect-your-stuff
17
+ */
18
+
19
+ /**
20
+ * DoubleLinker represents a node in a DoublyLinkedList.
21
+ * @extends Linker
22
+ */
23
+ class DoubleLinker extends _Linker.default {
24
+ prev = null;
25
+
26
+ /**
27
+ * Create the new DoubleLinker instance, provide the data and optionally configure the type of Linker.
28
+ * @param {Object} [nodeData={}]
29
+ * @param {*} [nodeData.data=null]
30
+ * @param {DoubleLinker|null} [nodeData.prev=null]
31
+ * @param {DoubleLinker|null} [nodeData.next=null]
32
+ * @param {DoubleLinker} [linkerClass=DoubleLinker]
33
+ */
34
+ constructor() {
35
+ let {
36
+ data = null,
37
+ prev = null,
38
+ next = null
39
+ } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
40
+ let linkerClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DoubleLinker;
41
+ super({
42
+ data: data,
43
+ next: next
44
+ }, linkerClass);
45
+ this.prev = prev;
46
+ }
47
+ }
48
+
49
+ /**
50
+ * Make a new DoubleLinker from the data given if it is not already a valid Linker.
51
+ * @methodof DoubleLinker
52
+ * @param {DoubleLinker|*} linker
53
+ * @param {DoubleLinker} [linkerClass=DoubleLinker]
54
+ * @return {Linker}
55
+ */
56
+ DoubleLinker.make = function (linker) {
57
+ let linkerClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DoubleLinker;
58
+ return _Linker.default.make(linker, linkerClass);
59
+ };
60
+
61
+ /**
62
+ * Convert an array into DoubleLinker instances, return the head and tail DoubleLinkers.
63
+ * @methodof DoubleLinker
64
+ * @param {Array} [values=[]]
65
+ * @param {DoubleLinker} [linkerClass=DoubleLinker]
66
+ * @returns {{head: DoubleLinker, tail: DoubleLinker}}
67
+ */
68
+ DoubleLinker.fromArray = function () {
69
+ let values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
70
+ let linkerClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : DoubleLinker;
71
+ return values.reduce((references, linker) => {
72
+ const newLinker = linkerClass.make(linker);
73
+ if (references.head === null) {
74
+ // Initialize the head and tail with the new node
75
+ return {
76
+ head: newLinker,
77
+ tail: newLinker
78
+ };
79
+ }
80
+ newLinker.prev = references.tail;
81
+ // Only update the tail once head has been set, tail is always the most recent node
82
+ references.tail.next = newLinker;
83
+ references.tail = newLinker;
84
+ return references;
85
+ }, {
86
+ head: null,
87
+ tail: null
88
+ });
89
+ };
90
+ var _default = exports.default = DoubleLinker;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0,require("core-js/modules/esnext.async-iterator.reduce.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js");var _Linker=_interopRequireDefault(require("../linked-list/Linker"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}class DoubleLinker extends _Linker.default{prev=null;constructor(){let{data:e=null,prev:r=null,next:t=null}=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};super({data:e,next:t},arguments.length>1&&void 0!==arguments[1]?arguments[1]:DoubleLinker),this.prev=r}}DoubleLinker.make=function(e){let r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:DoubleLinker;return _Linker.default.make(e,r)},DoubleLinker.fromArray=function(){let e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:DoubleLinker;return(arguments.length>0&&void 0!==arguments[0]?arguments[0]:[]).reduce(((r,t)=>{const l=e.make(t);return null===r.head?{head:l,tail:l}:(l.prev=r.tail,r.tail.next=l,r.tail=l,r)}),{head:null,tail:null})};var _default=exports.default=DoubleLinker;
@@ -0,0 +1,234 @@
1
+ 'use strict'
2
+
3
+ Object.defineProperty(exports, '__esModule', {
4
+ value: true
5
+ })
6
+ exports.default = void 0
7
+ var _DoubleLinker = _interopRequireDefault(require('./DoubleLinker'))
8
+ var _LinkedList = _interopRequireDefault(require('../linked-list/LinkedList'))
9
+ function _interopRequireDefault (obj) { return obj && obj.__esModule ? obj : { default: obj } }
10
+ /**
11
+ * @file doubly linked list.
12
+ * @author Joshua Heagle <joshuaheagle@gmail.com>
13
+ * @version 1.0.0
14
+ * @memberOf module:collect-your-stuff
15
+ */
16
+
17
+ /**
18
+ * DoublyLinkedList represents a collection stored as a LinkedList with prev and next references.
19
+ * @extends LinkedList
20
+ */
21
+ class DoublyLinkedList extends _LinkedList.default {
22
+ /**
23
+ * Create the new DoublyLinkedList instance, configure the Linker and List classes.
24
+ * @param {DoublyLinkedList|Iterable} [listClass=DoublyLinkedList]
25
+ */
26
+ constructor () {
27
+ const listClass = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DoublyLinkedList
28
+ super(listClass)
29
+ }
30
+
31
+ /**
32
+ * Retrieve the first DoubleLinker in the list.
33
+ * @returns {DoubleLinker}
34
+ */
35
+ get first () {
36
+ return this.reset()
37
+ }
38
+
39
+ /**
40
+ * Retrieve the last DoubleLinker in the list.
41
+ * @returns {DoubleLinker}
42
+ */
43
+ get last () {
44
+ let tail = this.innerList
45
+ let next = tail.next
46
+ while (next !== null) {
47
+ tail = next
48
+ next = tail.next
49
+ }
50
+ return tail
51
+ }
52
+
53
+ /**
54
+ * Return the length of the list.
55
+ * @returns {number}
56
+ */
57
+ get length () {
58
+ let current = this.first
59
+ let length = 0
60
+ while (current !== null) {
61
+ ++length
62
+ current = current.next
63
+ }
64
+ return length
65
+ }
66
+
67
+ /**
68
+ * Insert a new node (or data) after a node.
69
+ * @method
70
+ * @param {DoubleLinker|*} node
71
+ * @param {DoubleLinker|*} newNode
72
+ * @returns {DoublyLinkedList}
73
+ */
74
+ insertAfter (node, newNode) {
75
+ newNode = node.classType.make(newNode)
76
+ // Ensure the next reference of this node is assigned to the new node
77
+ newNode.next = node.next
78
+ // Ensure this node is assigned as the prev reference of the new node
79
+ newNode.prev = node
80
+ // Then set this node's next reference to the new node
81
+ node.next = newNode
82
+ if (newNode.next) {
83
+ // Update the next reference to ensure circular reference for prev points to the new node
84
+ newNode.next.prev = newNode
85
+ }
86
+ this.reset()
87
+ return this
88
+ }
89
+
90
+ /**
91
+ * Insert a new node (or data) before a node.
92
+ * @method
93
+ * @param {DoubleLinker|*} node
94
+ * @param {DoubleLinker|*} newNode
95
+ * @returns {DoublyLinkedList}
96
+ */
97
+ insertBefore (node, newNode) {
98
+ newNode = node.classType.make(newNode)
99
+ // The new node will reference this prev node as prev
100
+ newNode.prev = node.prev
101
+ // The new node will reference this node as next
102
+ newNode.next = node
103
+ // This prev will reference the new node
104
+ node.prev = newNode
105
+ if (newNode.prev) {
106
+ // Update the prev reference to ensure circular reference for next points to the new node
107
+ newNode.prev.next = newNode
108
+ }
109
+ this.reset()
110
+ return this
111
+ }
112
+
113
+ /**
114
+ * Remove a linker from this linked list.
115
+ * @method
116
+ * @param {DoubleLinker} node
117
+ * @return {DoubleLinker}
118
+ */
119
+ remove (node) {
120
+ if (node.prev) {
121
+ // The previous node will reference this next node
122
+ node.prev.next = node.next
123
+ }
124
+ if (node.next) {
125
+ // The next node will reference this previous node
126
+ node.next.prev = node.prev
127
+ }
128
+ // Update head reference
129
+ this.reset()
130
+ return node
131
+ }
132
+
133
+ /**
134
+ * Refresh all references and return head reference.
135
+ * @return {DoubleLinker}
136
+ */
137
+ reset () {
138
+ // Start at the pointer for the list
139
+ let pointer = this.innerList
140
+ let next = pointer.next
141
+ // Follow references till the end
142
+ while (next !== null) {
143
+ pointer = next
144
+ next = pointer.next
145
+ }
146
+ let prev = pointer.prev
147
+ // From final reference, follow references back to the beginning
148
+ while (prev !== null) {
149
+ pointer = prev
150
+ prev = pointer.prev
151
+ }
152
+ // All the live references should have been found and we are pointing to the true head
153
+ this.innerList = pointer
154
+ return pointer
155
+ }
156
+
157
+ /**
158
+ * Retrieve a DoubleLinker item from this list by numeric index, otherwise return null.
159
+ * @method
160
+ * @param {number} index
161
+ * @returns {DoubleLinker|null}
162
+ */
163
+ item (index) {
164
+ if (index >= 0) {
165
+ let current = this.first
166
+ let currentIndex = -1
167
+ while (++currentIndex < index && current !== null) {
168
+ current = current.next
169
+ }
170
+ return currentIndex === index ? current : null
171
+ }
172
+ let current = this.last
173
+ let currentIndex = this.length
174
+ const calculatedIndex = this.length + index
175
+ if (calculatedIndex < 0) {
176
+ return null
177
+ }
178
+ while (--currentIndex > calculatedIndex && current !== null) {
179
+ current = current.prev
180
+ }
181
+ return currentIndex === calculatedIndex ? current : null
182
+ }
183
+
184
+ /**
185
+ * Be able to run forEach on this DoublyLinkedList ot iterate over the DoubleLinker Items.
186
+ * @param {forEachCallback} callback
187
+ * @param {DoublyLinkedList} thisArg
188
+ */
189
+ forEach (callback) {
190
+ const thisArg = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this
191
+ let index = 0
192
+ let current = thisArg.first
193
+ while (current !== null) {
194
+ callback(current, index, thisArg)
195
+ current = current.next
196
+ ++index
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Be able to iterate over this class.
202
+ * @method
203
+ * @returns {Iterator}
204
+ */
205
+ [Symbol.iterator] () {
206
+ let current = this.first
207
+ return {
208
+ next: () => {
209
+ const result = {
210
+ value: current,
211
+ done: !current
212
+ }
213
+ current = current ? current.next : null
214
+ return result
215
+ }
216
+ }
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Convert an array into a DoublyLinkedList instance, return the new instance.
222
+ * @methodof DoublyLinkedList
223
+ * @param {Array} [values=[]]
224
+ * @param {DoubleLinker} [linkerClass=DoubleLinker]
225
+ * @param {DoublyLinkedList} [listClass=DoublyLinkedList]
226
+ * @returns {DoublyLinkedList}
227
+ */
228
+ DoublyLinkedList.fromArray = function () {
229
+ const values = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []
230
+ const linkerClass = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _DoubleLinker.default
231
+ const listClass = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DoublyLinkedList
232
+ return _LinkedList.default.fromArray(values, linkerClass, listClass)
233
+ }
234
+ var _default = exports.default = DoublyLinkedList
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=void 0;var _DoubleLinker=_interopRequireDefault(require("./DoubleLinker")),_LinkedList=_interopRequireDefault(require("../linked-list/LinkedList"));function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}class DoublyLinkedList extends _LinkedList.default{constructor(){super(arguments.length>0&&void 0!==arguments[0]?arguments[0]:DoublyLinkedList)}get first(){return this.reset()}get last(){let e=this.innerList,t=e.next;for(;null!==t;)e=t,t=e.next;return e}get length(){let e=this.first,t=0;for(;null!==e;)++t,e=e.next;return t}insertAfter(e,t){return(t=e.classType.make(t)).next=e.next,t.prev=e,e.next=t,t.next&&(t.next.prev=t),this.reset(),this}insertBefore(e,t){return(t=e.classType.make(t)).prev=e.prev,t.next=e,e.prev=t,t.prev&&(t.prev.next=t),this.reset(),this}remove(e){return e.prev&&(e.prev.next=e.next),e.next&&(e.next.prev=e.prev),this.reset(),e}reset(){let e=this.innerList,t=e.next;for(;null!==t;)e=t,t=e.next;let r=e.prev;for(;null!==r;)e=r,r=e.prev;return this.innerList=e,e}item(e){if(e>=0){let t=this.first,r=-1;for(;++r<e&&null!==t;)t=t.next;return r===e?t:null}let t=this.last,r=this.length;const n=this.length+e;if(n<0)return null;for(;--r>n&&null!==t;)t=t.prev;return r===n?t:null}forEach(e){let t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:this,r=0,n=t.first;for(;null!==n;)e(n,r,t),n=n.next,++r}[Symbol.iterator](){let e=this.first;return{next:()=>{const t={value:e,done:!e};return e=e?e.next:null,t}}}}DoublyLinkedList.fromArray=function(){let e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:_DoubleLinker.default,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:DoublyLinkedList;return _LinkedList.default.fromArray(e,t,r)};var _default=exports.default=DoublyLinkedList;