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.
- package/LICENSE +674 -0
- package/README.md +1676 -0
- package/browser/collect-your-stuff.js +18987 -0
- package/browser/collect-your-stuff.min.js +1 -0
- package/dist/collections/arrayable/ArrayElement.js +95 -0
- package/dist/collections/arrayable/ArrayElement.min.js +1 -0
- package/dist/collections/arrayable/Arrayable.js +253 -0
- package/dist/collections/arrayable/Arrayable.min.js +1 -0
- package/dist/collections/doubly-linked-llist/DoubleLinker.js +90 -0
- package/dist/collections/doubly-linked-llist/DoubleLinker.min.js +1 -0
- package/dist/collections/doubly-linked-llist/DoublyLinkedList.js +234 -0
- package/dist/collections/doubly-linked-llist/DoublyLinkedList.min.js +1 -0
- package/dist/collections/linked-list/LinkedList.js +256 -0
- package/dist/collections/linked-list/LinkedList.min.js +1 -0
- package/dist/collections/linked-list/Linker.js +100 -0
- package/dist/collections/linked-list/Linker.min.js +1 -0
- package/dist/collections/linked-tree-list/LinkedTreeList.js +96 -0
- package/dist/collections/linked-tree-list/LinkedTreeList.min.js +1 -0
- package/dist/collections/linked-tree-list/TreeLinker.js +112 -0
- package/dist/collections/linked-tree-list/TreeLinker.min.js +1 -0
- package/dist/collections/queue/Queue.js +163 -0
- package/dist/collections/queue/Queue.min.js +1 -0
- package/dist/collections/queue/Queueable.js +177 -0
- package/dist/collections/queue/Queueable.min.js +1 -0
- package/dist/collections/stack/Stack.js +141 -0
- package/dist/collections/stack/Stack.min.js +1 -0
- package/dist/collections/stack/Stackable.js +85 -0
- package/dist/collections/stack/Stackable.min.js +1 -0
- package/dist/main.js +44 -0
- package/dist/main.min.js +1 -0
- package/dist/recipes/Runnable.js +67 -0
- package/dist/recipes/Runnable.min.js +1 -0
- package/dist/recipes/recipes.js +23 -0
- package/dist/recipes/recipes.min.js +1 -0
- 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;
|