ts-linked-list
Advanced tools
Comparing version 0.0.1 to 0.0.2
@@ -140,5 +140,12 @@ /*! ***************************************************************************** | ||
* A doubly linked list | ||
* @constructor | ||
* @class | ||
* @namespace | ||
* ```javascript | ||
* const list = new LinkedList(1, 2); | ||
* list.append(3); | ||
* list.prepend(0); | ||
* list.forEach(data => console.log(data)); | ||
* // 0 1 2 3 | ||
* list.head.remove(); | ||
* console.log(list.toArray()); | ||
* // [1, 2, 3] | ||
* ``` | ||
*/ | ||
@@ -170,5 +177,8 @@ var LinkedList = /** @class */ (function () { | ||
/** | ||
* Convert an array to a linked list | ||
* @param {any[]} array An array | ||
* @returns {LinkedList} | ||
* Convert an array to a new linked list | ||
* ```javascript | ||
* import LinkedList from '@tuelsch/linked-list'; | ||
* const list = LinkedList.fromArray([1, 2, 3]); | ||
* ``` | ||
* @param array An array | ||
*/ | ||
@@ -175,0 +185,0 @@ LinkedList.fromArray = function (array) { |
1058
dist/index.js
@@ -1,557 +0,573 @@ | ||
'use strict'; | ||
(function (global, factory) { | ||
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : | ||
typeof define === 'function' && define.amd ? define(factory) : | ||
(global = global || self, global.LinkedList = factory()); | ||
}(this, function () { 'use strict'; | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
/*! ***************************************************************************** | ||
Copyright (c) Microsoft Corporation. All rights reserved. | ||
Licensed under the Apache License, Version 2.0 (the "License"); you may not use | ||
this file except in compliance with the License. You may obtain a copy of the | ||
License at http://www.apache.org/licenses/LICENSE-2.0 | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | ||
KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED | ||
WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, | ||
MERCHANTABLITY OR NON-INFRINGEMENT. | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */ | ||
See the Apache Version 2.0 License for specific language governing permissions | ||
and limitations under the License. | ||
***************************************************************************** */ | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
function __generator(thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
} | ||
function __values(o) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | ||
if (m) return m.call(o); | ||
return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
}; | ||
} | ||
} | ||
function __values(o) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | ||
if (m) return m.call(o); | ||
return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
} | ||
function __read(o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
function __read(o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
finally { if (e) throw e.error; } | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
} | ||
return ar; | ||
} | ||
function __spread() { | ||
for (var ar = [], i = 0; i < arguments.length; i++) | ||
ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
} | ||
function __spread() { | ||
for (var ar = [], i = 0; i < arguments.length; i++) | ||
ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
} | ||
var LinkedListNode = /** @class */ (function () { | ||
function LinkedListNode(data, prev, next, list) { | ||
this.data = data; | ||
this.prev = prev; | ||
this.next = next; | ||
this.list = list; | ||
} | ||
Object.defineProperty(LinkedListNode.prototype, "value", { | ||
var LinkedListNode = /** @class */ (function () { | ||
function LinkedListNode(data, prev, next, list) { | ||
this.data = data; | ||
this.prev = prev; | ||
this.next = next; | ||
this.list = list; | ||
} | ||
Object.defineProperty(LinkedListNode.prototype, "value", { | ||
/** | ||
* Alias to .data | ||
*/ | ||
get: function () { | ||
return this.data; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
/** | ||
* Alias to .data | ||
* Insert a new node before this one | ||
* @param {any} data Data to save in the node | ||
* @returns {LinkedList} | ||
*/ | ||
get: function () { | ||
return this.data; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
LinkedListNode.prototype.insertBefore = function (data) { | ||
if (this.list === null) { | ||
throw new ReferenceError('Node does not belong to any list'); | ||
} | ||
return this.list.insertBefore(this, data); | ||
}; | ||
/** | ||
* Insert a new node after this one | ||
* @param {any} data Data to be saved in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedListNode.prototype.insertAfter = function (data) { | ||
if (this.list === null) { | ||
throw new ReferenceError('Node does not belong to any list'); | ||
} | ||
return this.list.insertAfter(this, data); | ||
}; | ||
/** | ||
* Remove this node | ||
* @returns {LinkedList} the list without this node | ||
*/ | ||
LinkedListNode.prototype.remove = function () { | ||
if (this.list === null) { | ||
throw new ReferenceError('Node does not belong to any list'); | ||
} | ||
return this.list.removeNode(this); | ||
}; | ||
/** | ||
* Clone this node | ||
* NOTE: Data is not deeply cloned if it is not a simple data type | ||
* like string, integer, boolean, null or undefined | ||
*/ | ||
LinkedListNode.prototype.clone = function () { | ||
return new LinkedListNode(this.data, this.prev, this.next, this.list); | ||
}; | ||
return LinkedListNode; | ||
}()); | ||
/** | ||
* Insert a new node before this one | ||
* @param {any} data Data to save in the node | ||
* @returns {LinkedList} | ||
* A doubly linked list | ||
* ```javascript | ||
* const list = new LinkedList(1, 2); | ||
* list.append(3); | ||
* list.prepend(0); | ||
* list.forEach(data => console.log(data)); | ||
* // 0 1 2 3 | ||
* list.head.remove(); | ||
* console.log(list.toArray()); | ||
* // [1, 2, 3] | ||
* ``` | ||
*/ | ||
LinkedListNode.prototype.insertBefore = function (data) { | ||
if (this.list === null) { | ||
throw new ReferenceError('Node does not belong to any list'); | ||
} | ||
return this.list.insertBefore(this, data); | ||
}; | ||
/** | ||
* Insert a new node after this one | ||
* @param {any} data Data to be saved in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedListNode.prototype.insertAfter = function (data) { | ||
if (this.list === null) { | ||
throw new ReferenceError('Node does not belong to any list'); | ||
} | ||
return this.list.insertAfter(this, data); | ||
}; | ||
/** | ||
* Remove this node | ||
* @returns {LinkedList} the list without this node | ||
*/ | ||
LinkedListNode.prototype.remove = function () { | ||
if (this.list === null) { | ||
throw new ReferenceError('Node does not belong to any list'); | ||
} | ||
return this.list.removeNode(this); | ||
}; | ||
/** | ||
* Clone this node | ||
* NOTE: Data is not deeply cloned if it is not a simple data type | ||
* like string, integer, boolean, null or undefined | ||
*/ | ||
LinkedListNode.prototype.clone = function () { | ||
return new LinkedListNode(this.data, this.prev, this.next, this.list); | ||
}; | ||
return LinkedListNode; | ||
}()); | ||
/** | ||
* A doubly linked list | ||
* @constructor | ||
* @class | ||
* @namespace | ||
*/ | ||
var LinkedList = /** @class */ (function () { | ||
function LinkedList() { | ||
var e_1, _a; | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
this.head = null; | ||
this.tail = null; | ||
this.size = 0; | ||
try { | ||
for (var args_1 = __values(args), args_1_1 = args_1.next(); !args_1_1.done; args_1_1 = args_1.next()) { | ||
var data = args_1_1.value; | ||
this.append(data); | ||
var LinkedList = /** @class */ (function () { | ||
function LinkedList() { | ||
var e_1, _a; | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
this.head = null; | ||
this.tail = null; | ||
this.size = 0; | ||
try { | ||
if (args_1_1 && !args_1_1.done && (_a = args_1.return)) _a.call(args_1); | ||
for (var args_1 = __values(args), args_1_1 = args_1.next(); !args_1_1.done; args_1_1 = args_1.next()) { | ||
var data = args_1_1.value; | ||
this.append(data); | ||
} | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (args_1_1 && !args_1_1.done && (_a = args_1.return)) _a.call(args_1); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
} | ||
} | ||
/** | ||
* Convert an array to a linked list | ||
* @param {any[]} array An array | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.fromArray = function (array) { | ||
var list = new LinkedList(); | ||
array.forEach(function (data) { return list.append(data); }); | ||
return list; | ||
}; | ||
/** | ||
* The iterator implementation | ||
*/ | ||
LinkedList.prototype[Symbol.iterator] = function () { | ||
var element; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
element = this.head; | ||
_a.label = 1; | ||
case 1: | ||
if (!(element !== null)) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, element.data]; | ||
case 2: | ||
_a.sent(); | ||
element = element.next; | ||
return [3 /*break*/, 1]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
/** | ||
* Convert an array to a new linked list | ||
* ```javascript | ||
* import LinkedList from '@tuelsch/linked-list'; | ||
* const list = LinkedList.fromArray([1, 2, 3]); | ||
* ``` | ||
* @param array An array | ||
*/ | ||
LinkedList.fromArray = function (array) { | ||
var list = new LinkedList(); | ||
array.forEach(function (data) { return list.append(data); }); | ||
return list; | ||
}; | ||
/** | ||
* The iterator implementation | ||
*/ | ||
LinkedList.prototype[Symbol.iterator] = function () { | ||
var element; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
element = this.head; | ||
_a.label = 1; | ||
case 1: | ||
if (!(element !== null)) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, element.data]; | ||
case 2: | ||
_a.sent(); | ||
element = element.next; | ||
return [3 /*break*/, 1]; | ||
case 3: return [2 /*return*/]; | ||
} | ||
}); | ||
}; | ||
Object.defineProperty(LinkedList.prototype, "length", { | ||
/** | ||
* The length of the list | ||
* @returns {number} | ||
*/ | ||
get: function () { | ||
return this.size; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
}; | ||
Object.defineProperty(LinkedList.prototype, "length", { | ||
/** | ||
* The length of the list | ||
* @returns {number} | ||
* Get the node data at a specified index, zero based | ||
* @param index to retrieve data at | ||
* @returns {any} Data or undefined | ||
*/ | ||
get: function () { | ||
return this.size; | ||
}, | ||
enumerable: true, | ||
configurable: true | ||
}); | ||
/** | ||
* Get the node data at a specified index, zero based | ||
* @param index to retrieve data at | ||
* @returns {any} Data or undefined | ||
*/ | ||
LinkedList.prototype.get = function (index) { | ||
var node = this.getNode(index); | ||
return node !== undefined ? node.data : undefined; | ||
}; | ||
/** | ||
* Get the node at index, zero based | ||
* @param index to retrieve the node at | ||
* @returns {LinkedListNode|undefined} The node or undefined | ||
*/ | ||
LinkedList.prototype.getNode = function (index) { | ||
if (this.head === null || index < 0) { | ||
LinkedList.prototype.get = function (index) { | ||
var node = this.getNode(index); | ||
return node !== undefined ? node.data : undefined; | ||
}; | ||
/** | ||
* Get the node at index, zero based | ||
* @param index to retrieve the node at | ||
* @returns {LinkedListNode|undefined} The node or undefined | ||
*/ | ||
LinkedList.prototype.getNode = function (index) { | ||
if (this.head === null || index < 0) { | ||
return undefined; | ||
} | ||
var currentIndex = 0; | ||
var currentNode = this.head; | ||
for (; currentIndex < index && currentNode !== null; currentIndex += 1) { | ||
currentNode = currentNode.next; | ||
} | ||
return currentNode !== null ? currentNode : undefined; | ||
}; | ||
LinkedList.prototype.findNodeIndex = function (f) { | ||
var currentIndex = 0; | ||
var currentNode = this.head; | ||
while (currentNode) { | ||
if (f(currentNode.data, currentIndex, this)) { | ||
return { | ||
index: currentIndex, | ||
node: currentNode, | ||
}; | ||
} | ||
currentNode = currentNode.next; | ||
currentIndex += 1; | ||
} | ||
return undefined; | ||
} | ||
var currentIndex = 0; | ||
var currentNode = this.head; | ||
for (; currentIndex < index && currentNode !== null; currentIndex += 1) { | ||
currentNode = currentNode.next; | ||
} | ||
return currentNode !== null ? currentNode : undefined; | ||
}; | ||
LinkedList.prototype.findNodeIndex = function (f) { | ||
var currentIndex = 0; | ||
var currentNode = this.head; | ||
while (currentNode) { | ||
if (f(currentNode.data, currentIndex, this)) { | ||
return { | ||
index: currentIndex, | ||
node: currentNode, | ||
}; | ||
}; | ||
/** | ||
* Returns the first node in the list that | ||
* satisfies the provided testing function. Otherwise undefined is returned. | ||
* @param f Function to test data against | ||
*/ | ||
LinkedList.prototype.findNode = function (f) { | ||
var nodeIndex = this.findNodeIndex(f); | ||
return nodeIndex !== undefined ? nodeIndex.node : undefined; | ||
}; | ||
/** | ||
* Returns the value of the first element in the list that | ||
* satisfies the provided testing function. Otherwise undefined is returned. | ||
* @param f Function to test data against | ||
*/ | ||
LinkedList.prototype.find = function (f) { | ||
var nodeIndex = this.findNodeIndex(f); | ||
return nodeIndex !== undefined ? nodeIndex.node.data : undefined; | ||
}; | ||
/** | ||
* Returns the index of the first node in the list that | ||
* satisfies the provided testing function. Ohterwise -1 is returned. | ||
* @param f Function to test data against | ||
*/ | ||
LinkedList.prototype.findIndex = function (f) { | ||
var nodeIndex = this.findNodeIndex(f); | ||
return nodeIndex !== undefined ? nodeIndex.index : -1; | ||
}; | ||
/** | ||
* Append a node to the end of the list | ||
* @param {any} data Data to be stored in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.append = function (data) { | ||
var node = new LinkedListNode(data, this.tail, null, this); | ||
if (this.head === null) { | ||
this.head = node; | ||
} | ||
currentNode = currentNode.next; | ||
currentIndex += 1; | ||
} | ||
return undefined; | ||
}; | ||
/** | ||
* Returns the first node in the list that | ||
* satisfies the provided testing function. Otherwise undefined is returned. | ||
* @param f Function to test data against | ||
*/ | ||
LinkedList.prototype.findNode = function (f) { | ||
var nodeIndex = this.findNodeIndex(f); | ||
return nodeIndex !== undefined ? nodeIndex.node : undefined; | ||
}; | ||
/** | ||
* Returns the value of the first element in the list that | ||
* satisfies the provided testing function. Otherwise undefined is returned. | ||
* @param f Function to test data against | ||
*/ | ||
LinkedList.prototype.find = function (f) { | ||
var nodeIndex = this.findNodeIndex(f); | ||
return nodeIndex !== undefined ? nodeIndex.node.data : undefined; | ||
}; | ||
/** | ||
* Returns the index of the first node in the list that | ||
* satisfies the provided testing function. Ohterwise -1 is returned. | ||
* @param f Function to test data against | ||
*/ | ||
LinkedList.prototype.findIndex = function (f) { | ||
var nodeIndex = this.findNodeIndex(f); | ||
return nodeIndex !== undefined ? nodeIndex.index : -1; | ||
}; | ||
/** | ||
* Append a node to the end of the list | ||
* @param {any} data Data to be stored in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.append = function (data) { | ||
var node = new LinkedListNode(data, this.tail, null, this); | ||
if (this.head === null) { | ||
this.head = node; | ||
} | ||
if (this.tail !== null) { | ||
this.tail.next = node; | ||
} | ||
this.tail = node; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Synonym for append | ||
* @param data Data to be stored | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.push = function (data) { | ||
return this.append(data); | ||
}; | ||
/** | ||
* Prepend a node to the beginning of the list | ||
* @param {any} data Data to be stored in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.prepend = function (data) { | ||
var node = new LinkedListNode(data, null, this.head, this); | ||
if (this.tail === null) { | ||
if (this.tail !== null) { | ||
this.tail.next = node; | ||
} | ||
this.tail = node; | ||
} | ||
if (this.head !== null) { | ||
this.head.prev = node; | ||
} | ||
this.head = node; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Insert a new node at a given index position. If index is | ||
* out of bounds, the node is appended, if index is negative | ||
* or 0, it will be prepended. | ||
* @param {number} index The index to insert the new node at | ||
* @param {any} data Data to be stored on the new node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.insertAt = function (index, data) { | ||
if (this.head === null) { | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Synonym for append | ||
* @param data Data to be stored | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.push = function (data) { | ||
return this.append(data); | ||
} | ||
if (index <= 0) { | ||
return this.prepend(data); | ||
} | ||
var currentNode = this.head; | ||
var currentIndex = 0; | ||
while (currentIndex < index - 1 && currentNode.next !== null) { | ||
currentIndex += 1; | ||
currentNode = currentNode.next; | ||
} | ||
currentNode.insertAfter(data); | ||
return this; | ||
}; | ||
/** | ||
* Remove the specified node from the list | ||
* @param node The node to be removed | ||
* @returns {LinkedListNode} The removed node | ||
*/ | ||
LinkedList.prototype.removeNode = function (node) { | ||
if (node.list !== this) { | ||
throw new ReferenceError('Node does not belong to this list'); | ||
} | ||
if (node.prev !== null) { | ||
node.prev.next = node.next; | ||
} | ||
if (node.next !== null) { | ||
node.next.prev = node.prev; | ||
} | ||
if (this.head === node) { | ||
this.head = node.next; | ||
} | ||
if (this.tail === node) { | ||
this.tail = node.prev; | ||
} | ||
this.size -= 1; | ||
node.next = null; | ||
node.prev = null; | ||
node.list = null; | ||
return node; | ||
}; | ||
/** | ||
* Remove the node at the specified index | ||
* @param {number} index Index at which to remove | ||
* @returns {LinkedListNode} The removed node or undefined | ||
*/ | ||
LinkedList.prototype.removeAt = function (index) { | ||
var node = this.getNode(index); | ||
return node !== undefined ? this.removeNode(node) : undefined; | ||
}; | ||
/** | ||
* Insert a new node before the reference node | ||
* @param {LinkedListNode} referenceNode The node reference | ||
* @param {any} data Data to save in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.insertBefore = function (referenceNode, data) { | ||
var node = new LinkedListNode(data, referenceNode.prev, referenceNode, this); | ||
if (referenceNode.prev === null) { | ||
}; | ||
/** | ||
* Prepend a node to the beginning of the list | ||
* @param {any} data Data to be stored in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.prepend = function (data) { | ||
var node = new LinkedListNode(data, null, this.head, this); | ||
if (this.tail === null) { | ||
this.tail = node; | ||
} | ||
if (this.head !== null) { | ||
this.head.prev = node; | ||
} | ||
this.head = node; | ||
} | ||
if (referenceNode.prev !== null) { | ||
referenceNode.prev.next = node; | ||
} | ||
referenceNode.prev = node; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Insert a new node after this one | ||
* @param {LinkedListNode} referenceNode The reference node | ||
* @param {any} data Data to be saved in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.insertAfter = function (referenceNode, data) { | ||
var node = new LinkedListNode(data, referenceNode, referenceNode.next, this); | ||
if (referenceNode.next === null) { | ||
this.tail = node; | ||
} | ||
if (referenceNode.next !== null) { | ||
referenceNode.next.prev = node; | ||
} | ||
referenceNode.next = node; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Remove the first node from the list | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.shift = function () { | ||
if (this.head === null) { | ||
return undefined; | ||
} | ||
return this.removeNode(this.head).data; | ||
}; | ||
/** | ||
* Remove the last node from the list | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.pop = function () { | ||
if (this.tail === null) { | ||
return undefined; | ||
} | ||
return this.removeNode(this.tail).data; | ||
}; | ||
/** | ||
* Concatenate the current list with another | ||
* @param {LinkedList} list The list to be linked | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.concat = function (list) { | ||
if (list.head !== null) { | ||
var link = new LinkedListNode(list.head.data, this.tail, list.head.next, this); | ||
if (this.tail !== null) { | ||
this.tail.next = link; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Insert a new node at a given index position. If index is | ||
* out of bounds, the node is appended, if index is negative | ||
* or 0, it will be prepended. | ||
* @param {number} index The index to insert the new node at | ||
* @param {any} data Data to be stored on the new node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.insertAt = function (index, data) { | ||
if (this.head === null) { | ||
return this.append(data); | ||
} | ||
} | ||
this.head = this.head || list.head; | ||
this.tail = list.tail || this.tail; | ||
this.size += list.size; | ||
return this; | ||
}; | ||
/** | ||
* The slice() method returns a shallow copy of a | ||
* portion of a list into a new list object selected | ||
* from begin to end (end not included). | ||
* The original array will not be modified. | ||
* @param {number} start Start index | ||
* @param {number} end End index, optional | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.slice = function (start, end) { | ||
var list = new LinkedList(); | ||
var finish = end; | ||
if (this.head === null || this.tail === null) { | ||
return list; | ||
} | ||
if (finish === undefined || finish < start) { | ||
finish = this.length; | ||
} | ||
var head = this.getNode(start); | ||
for (var i = 0; i < finish - start && head !== null && head !== undefined; i++) { | ||
list.append(head.data); | ||
head = head.next; | ||
} | ||
return list; | ||
}; | ||
/** | ||
* The forEach() method executes a provided function once for each list node. | ||
* @param {TMapFunction} f Function to execute for each element, taking three arguments. | ||
*/ | ||
LinkedList.prototype.forEach = function (f) { | ||
var e_2, _a; | ||
var currentIndex = 0; | ||
try { | ||
for (var _b = __values(this), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var data = _c.value; | ||
f(data, currentIndex, this); | ||
if (index <= 0) { | ||
return this.prepend(data); | ||
} | ||
var currentNode = this.head; | ||
var currentIndex = 0; | ||
while (currentIndex < index - 1 && currentNode.next !== null) { | ||
currentIndex += 1; | ||
currentNode = currentNode.next; | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
currentNode.insertAfter(data); | ||
return this; | ||
}; | ||
/** | ||
* Remove the specified node from the list | ||
* @param node The node to be removed | ||
* @returns {LinkedListNode} The removed node | ||
*/ | ||
LinkedList.prototype.removeNode = function (node) { | ||
if (node.list !== this) { | ||
throw new ReferenceError('Node does not belong to this list'); | ||
} | ||
if (node.prev !== null) { | ||
node.prev.next = node.next; | ||
} | ||
if (node.next !== null) { | ||
node.next.prev = node.prev; | ||
} | ||
if (this.head === node) { | ||
this.head = node.next; | ||
} | ||
if (this.tail === node) { | ||
this.tail = node.prev; | ||
} | ||
this.size -= 1; | ||
node.next = null; | ||
node.prev = null; | ||
node.list = null; | ||
return node; | ||
}; | ||
/** | ||
* Remove the node at the specified index | ||
* @param {number} index Index at which to remove | ||
* @returns {LinkedListNode} The removed node or undefined | ||
*/ | ||
LinkedList.prototype.removeAt = function (index) { | ||
var node = this.getNode(index); | ||
return node !== undefined ? this.removeNode(node) : undefined; | ||
}; | ||
/** | ||
* Insert a new node before the reference node | ||
* @param {LinkedListNode} referenceNode The node reference | ||
* @param {any} data Data to save in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.insertBefore = function (referenceNode, data) { | ||
var node = new LinkedListNode(data, referenceNode.prev, referenceNode, this); | ||
if (referenceNode.prev === null) { | ||
this.head = node; | ||
} | ||
if (referenceNode.prev !== null) { | ||
referenceNode.prev.next = node; | ||
} | ||
referenceNode.prev = node; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Insert a new node after this one | ||
* @param {LinkedListNode} referenceNode The reference node | ||
* @param {any} data Data to be saved in the node | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.insertAfter = function (referenceNode, data) { | ||
var node = new LinkedListNode(data, referenceNode, referenceNode.next, this); | ||
if (referenceNode.next === null) { | ||
this.tail = node; | ||
} | ||
if (referenceNode.next !== null) { | ||
referenceNode.next.prev = node; | ||
} | ||
referenceNode.next = node; | ||
this.size += 1; | ||
return this; | ||
}; | ||
/** | ||
* Remove the first node from the list | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.shift = function () { | ||
if (this.head === null) { | ||
return undefined; | ||
} | ||
return this.removeNode(this.head).data; | ||
}; | ||
/** | ||
* Remove the last node from the list | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.pop = function () { | ||
if (this.tail === null) { | ||
return undefined; | ||
} | ||
return this.removeNode(this.tail).data; | ||
}; | ||
/** | ||
* Concatenate the current list with another | ||
* @param {LinkedList} list The list to be linked | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.concat = function (list) { | ||
if (list.head !== null) { | ||
var link = new LinkedListNode(list.head.data, this.tail, list.head.next, this); | ||
if (this.tail !== null) { | ||
this.tail.next = link; | ||
} | ||
} | ||
this.head = this.head || list.head; | ||
this.tail = list.tail || this.tail; | ||
this.size += list.size; | ||
return this; | ||
}; | ||
/** | ||
* The slice() method returns a shallow copy of a | ||
* portion of a list into a new list object selected | ||
* from begin to end (end not included). | ||
* The original array will not be modified. | ||
* @param {number} start Start index | ||
* @param {number} end End index, optional | ||
* @returns {LinkedList} | ||
*/ | ||
LinkedList.prototype.slice = function (start, end) { | ||
var list = new LinkedList(); | ||
var finish = end; | ||
if (this.head === null || this.tail === null) { | ||
return list; | ||
} | ||
if (finish === undefined || finish < start) { | ||
finish = this.length; | ||
} | ||
var head = this.getNode(start); | ||
for (var i = 0; i < finish - start && head !== null && head !== undefined; i++) { | ||
list.append(head.data); | ||
head = head.next; | ||
} | ||
return list; | ||
}; | ||
/** | ||
* The forEach() method executes a provided function once for each list node. | ||
* @param {TMapFunction} f Function to execute for each element, taking three arguments. | ||
*/ | ||
LinkedList.prototype.forEach = function (f) { | ||
var e_2, _a; | ||
var currentIndex = 0; | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
for (var _b = __values(this), _c = _b.next(); !_c.done; _c = _b.next()) { | ||
var data = _c.value; | ||
f(data, currentIndex, this); | ||
currentIndex += 1; | ||
} | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
}; | ||
/** | ||
* Map over every node in the list and apply a function to each node | ||
* @param {TMapFunction} f A function to be applied to every node in the list | ||
* @returns {LinkedList} A new LinkedList | ||
*/ | ||
LinkedList.prototype.map = function (f) { | ||
var _this = this; | ||
var list = new LinkedList(); | ||
this.forEach(function (data, index) { return list.append(f(data, index, _this)); }); | ||
return list; | ||
}; | ||
/** | ||
* Filter the linked list | ||
* @param {TTestFunction} f A filter function | ||
* @returns {LinkedList} A new linked list | ||
*/ | ||
LinkedList.prototype.filter = function (f) { | ||
var _this = this; | ||
var list = new LinkedList(); | ||
this.forEach(function (data, index) { | ||
if (f(data, index, _this)) { | ||
list.append(data); | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (_c && !_c.done && (_a = _b.return)) _a.call(_b); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
}); | ||
return list; | ||
}; | ||
/** | ||
* Reduce over each node in the list | ||
* @param f A reducer function | ||
* @param start An initial value | ||
* @returns {any} The final state of the accumulator | ||
*/ | ||
LinkedList.prototype.reduce = function (f, start) { | ||
if (this.head === null) { | ||
return start; | ||
} | ||
var currentIndex = 0; | ||
var currentElement = start === undefined ? this.head.next : this.head; | ||
var result = start === undefined ? this.head.data : start; | ||
while (currentElement) { | ||
result = f(result, currentElement.data, currentIndex, this); | ||
currentIndex += 1; | ||
currentElement = currentElement.next; | ||
} | ||
return result; | ||
}; | ||
/** | ||
* Convert the linked list to an array | ||
* @returns {any[]} | ||
*/ | ||
LinkedList.prototype.toArray = function () { | ||
return __spread(this); | ||
}; | ||
}; | ||
/** | ||
* Map over every node in the list and apply a function to each node | ||
* @param {TMapFunction} f A function to be applied to every node in the list | ||
* @returns {LinkedList} A new LinkedList | ||
*/ | ||
LinkedList.prototype.map = function (f) { | ||
var _this = this; | ||
var list = new LinkedList(); | ||
this.forEach(function (data, index) { return list.append(f(data, index, _this)); }); | ||
return list; | ||
}; | ||
/** | ||
* Filter the linked list | ||
* @param {TTestFunction} f A filter function | ||
* @returns {LinkedList} A new linked list | ||
*/ | ||
LinkedList.prototype.filter = function (f) { | ||
var _this = this; | ||
var list = new LinkedList(); | ||
this.forEach(function (data, index) { | ||
if (f(data, index, _this)) { | ||
list.append(data); | ||
} | ||
}); | ||
return list; | ||
}; | ||
/** | ||
* Reduce over each node in the list | ||
* @param f A reducer function | ||
* @param start An initial value | ||
* @returns {any} The final state of the accumulator | ||
*/ | ||
LinkedList.prototype.reduce = function (f, start) { | ||
if (this.head === null) { | ||
return start; | ||
} | ||
var currentIndex = 0; | ||
var currentElement = start === undefined ? this.head.next : this.head; | ||
var result = start === undefined ? this.head.data : start; | ||
while (currentElement) { | ||
result = f(result, currentElement.data, currentIndex, this); | ||
currentIndex += 1; | ||
currentElement = currentElement.next; | ||
} | ||
return result; | ||
}; | ||
/** | ||
* Convert the linked list to an array | ||
* @returns {any[]} | ||
*/ | ||
LinkedList.prototype.toArray = function () { | ||
return __spread(this); | ||
}; | ||
return LinkedList; | ||
}()); | ||
return LinkedList; | ||
}()); | ||
module.exports = LinkedList; | ||
})); |
@@ -6,11 +6,21 @@ import LinkedListNode from './LinkedListNode'; | ||
* A doubly linked list | ||
* @constructor | ||
* @class | ||
* @namespace | ||
* ```javascript | ||
* const list = new LinkedList(1, 2); | ||
* list.append(3); | ||
* list.prepend(0); | ||
* list.forEach(data => console.log(data)); | ||
* // 0 1 2 3 | ||
* list.head.remove(); | ||
* console.log(list.toArray()); | ||
* // [1, 2, 3] | ||
* ``` | ||
*/ | ||
export default class LinkedList { | ||
/** | ||
* Convert an array to a linked list | ||
* @param {any[]} array An array | ||
* @returns {LinkedList} | ||
* Convert an array to a new linked list | ||
* ```javascript | ||
* import LinkedList from '@tuelsch/linked-list'; | ||
* const list = LinkedList.fromArray([1, 2, 3]); | ||
* ``` | ||
* @param array An array | ||
*/ | ||
@@ -17,0 +27,0 @@ static fromArray(array: any[]): LinkedList; |
{ | ||
"name": "ts-linked-list", | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"description": "A doubly linked list implementation", | ||
"main": "dist/index.js", | ||
"min": "dist/index.min.js", | ||
"module": "dist/index.es.js", | ||
@@ -26,2 +27,3 @@ "files": [ | ||
"rollup-plugin-typescript2": "^0.18.1", | ||
"rollup-plugin-uglify": "^6.0.1", | ||
"ts-jest": "^23.10.5", | ||
@@ -28,0 +30,0 @@ "tslint": "^5.12.0", |
@@ -1,2 +0,2 @@ | ||
# linked-list | ||
# ts-linked-list | ||
Yet another yet another doubly linked list, written in TypeScript. | ||
@@ -8,3 +8,3 @@ | ||
```shell | ||
npm install @tuelsch/linked-list | ||
npm install ts-linked-list | ||
``` | ||
@@ -14,3 +14,3 @@ | ||
```ts | ||
import LinkedList from '@tuelsch/linked-list'; | ||
import LinkedList from 'ts-linked-list'; | ||
@@ -38,2 +38,3 @@ // Create a list with however many arguments of whatever type you like | ||
![Dev Dependencies](https://david-dm.org/tuelsch/linked-list/dev-status.svg) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/tuelsch/ts-linked-list.svg)](https://greenkeeper.io/) | ||
@@ -40,0 +41,0 @@ This library does not have any dependencies, so the first badge is easy to keep green. The second will be more useful in the future to check wether the devtools need an update. |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
60963
8
1361
60
9