From fde5af1f1c8c550b08057662f9604732bd4c33e3 Mon Sep 17 00:00:00 2001 From: Revone Date: Wed, 20 Nov 2024 22:07:42 +1300 Subject: [PATCH] fix: #114. feat: Enhanced SinglyLinkedList methods to support Node type parameters for push, unshift, addAfter, addBefore, getNode, addAt, delete, indexOf; added a new get method. --- CHANGELOG.md | 2 +- package-lock.json | 52 +-- package.json | 10 +- .../linked-list/doubly-linked-list.ts | 56 ++-- .../linked-list/singly-linked-list.ts | 303 ++++++++++++------ 5 files changed, 274 insertions(+), 149 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5844356..ceecc29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - [Semantic Versioning](https://semver.org/spec/v2.0.0.html) - [`auto-changelog`](https://github.com/CookPete/auto-changelog) -## [v1.53.4](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming) +## [v1.53.5](https://github.com/zrwusa/data-structure-typed/compare/v1.51.5...main) (upcoming) ### Changes diff --git a/package-lock.json b/package-lock.json index 12065e0..7c5d51d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "data-structure-typed", - "version": "1.53.4", + "version": "1.53.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "data-structure-typed", - "version": "1.53.4", + "version": "1.53.5", "license": "MIT", "devDependencies": { "@eslint/compat": "^1.2.2", @@ -19,11 +19,11 @@ "@typescript-eslint/eslint-plugin": "^8.12.1", "@typescript-eslint/parser": "^8.12.1", "auto-changelog": "^2.5.0", - "avl-tree-typed": "^1.53.3", + "avl-tree-typed": "^1.53.4", "benchmark": "^2.1.4", - "binary-tree-typed": "^1.53.3", - "bst-typed": "^1.53.3", - "data-structure-typed": "^1.53.3", + "binary-tree-typed": "^1.53.4", + "bst-typed": "^1.53.4", + "data-structure-typed": "^1.53.4", "dependency-cruiser": "^16.5.0", "doctoc": "^2.2.1", "eslint": "^9.13.0", @@ -32,7 +32,7 @@ "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", "fast-glob": "^3.3.2", - "heap-typed": "^1.53.3", + "heap-typed": "^1.53.4", "istanbul-badges-readme": "^1.9.0", "jest": "^29.7.0", "js-sdsl": "^4.4.2", @@ -3437,13 +3437,13 @@ } }, "node_modules/avl-tree-typed": { - "version": "1.53.3", - "resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.53.3.tgz", - "integrity": "sha512-cDJlPy25fa2ry8oWt8W1h9ijBGYm8hvbf+CGyi6WrcZ9hvUbJV0zfdladdL8un6S5vyMU2PT57W1H7uqhHBqMQ==", + "version": "1.53.4", + "resolved": "https://registry.npmjs.org/avl-tree-typed/-/avl-tree-typed-1.53.4.tgz", + "integrity": "sha512-dZMEutl5xMp/n54V6W6SugCXdmfcgy+6esqlpjG47nQfrQ3WMQzx2oytMWRZa6Y+nDtDNefbwlEOO/fLKZUHyQ==", "dev": true, "license": "MIT", "dependencies": { - "data-structure-typed": "^1.53.3" + "data-structure-typed": "^1.53.4" } }, "node_modules/babel-jest": { @@ -3602,13 +3602,13 @@ } }, "node_modules/binary-tree-typed": { - "version": "1.53.3", - "resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.53.3.tgz", - "integrity": "sha512-pyjbqPkaw7RnQE9KJUpIEdiQU9o0ZfwtQTflCr9/40segAF6tZ8Llf6JMB0n7tg1CHW3Ru6k0FOEamc7BXJKug==", + "version": "1.53.4", + "resolved": "https://registry.npmjs.org/binary-tree-typed/-/binary-tree-typed-1.53.4.tgz", + "integrity": "sha512-/yDQUWHdT1HQBkMVTGZuo+Nn/nx1JnV5ERBFIKCdDVBvG2qKmTa5RlSC7rnjLzLsQz28qVHvisjoRYBhcQpCWg==", "dev": true, "license": "MIT", "dependencies": { - "data-structure-typed": "^1.53.3" + "data-structure-typed": "^1.53.4" } }, "node_modules/brace-expansion": { @@ -3691,13 +3691,13 @@ } }, "node_modules/bst-typed": { - "version": "1.53.3", - "resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.53.3.tgz", - "integrity": "sha512-qgI2TFaK9o9M00Td632glUzFJYRfjiPICHvQY5btzv3QzT+KUhZqBmqEtbwwx8qFHJy/Wz96sFMUx/PlfbYioQ==", + "version": "1.53.4", + "resolved": "https://registry.npmjs.org/bst-typed/-/bst-typed-1.53.4.tgz", + "integrity": "sha512-hjTK/CcW2hw0yAtazhFOl7lsNq598FuNwCgbcjpFgXk51swLwJ5P5Sm70UzwVns1LSdIulTK49zil9tGs6zv1g==", "dev": true, "license": "MIT", "dependencies": { - "data-structure-typed": "^1.53.3" + "data-structure-typed": "^1.53.4" } }, "node_modules/buffer-from": { @@ -4069,9 +4069,9 @@ } }, "node_modules/data-structure-typed": { - "version": "1.53.3", - "resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.53.3.tgz", - "integrity": "sha512-hIfGCq40JOjqoZ8CjwTZgdi76ow7gn1LUPDpeDoQ47v6yiWDPA7kkOd8AmGaqBFSKhkBbGPa85ipg28u/zpRKw==", + "version": "1.53.4", + "resolved": "https://registry.npmjs.org/data-structure-typed/-/data-structure-typed-1.53.4.tgz", + "integrity": "sha512-sMmlWv2wMqUVPnBemYc7RQMYtM0AXQq0m9drVeu0eMtpSvojvFb4hW+hzpd6IBtULguNw2YBG9EyNo7irlpavQ==", "dev": true, "license": "MIT" }, @@ -5946,13 +5946,13 @@ } }, "node_modules/heap-typed": { - "version": "1.53.3", - "resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.53.3.tgz", - "integrity": "sha512-eISjbd808zDUhJ1azWIlkLXQgGj6IOasO8yGAhI/NOkQ/Y3J9+5k3gx3llMoyiL5XQKbZ5+tHtoqQ4bfSELjVg==", + "version": "1.53.4", + "resolved": "https://registry.npmjs.org/heap-typed/-/heap-typed-1.53.4.tgz", + "integrity": "sha512-/lktvgpfH7Y2q8XpMFYCEebRIo5nM85DCR19zUeo3soVrxa2H90vJAKJJ0cPP/DEJ2cDggMk/Cuo4k4LLhbf7A==", "dev": true, "license": "MIT", "dependencies": { - "data-structure-typed": "^1.53.3" + "data-structure-typed": "^1.53.4" } }, "node_modules/html-escaper": { diff --git a/package.json b/package.json index de04641..08779bc 100644 --- a/package.json +++ b/package.json @@ -70,11 +70,11 @@ "@typescript-eslint/eslint-plugin": "^8.12.1", "@typescript-eslint/parser": "^8.12.1", "auto-changelog": "^2.5.0", - "avl-tree-typed": "^1.53.3", + "avl-tree-typed": "^1.53.4", "benchmark": "^2.1.4", - "binary-tree-typed": "^1.53.3", - "bst-typed": "^1.53.3", - "data-structure-typed": "^1.53.3", + "binary-tree-typed": "^1.53.4", + "bst-typed": "^1.53.4", + "data-structure-typed": "^1.53.4", "dependency-cruiser": "^16.5.0", "doctoc": "^2.2.1", "eslint": "^9.13.0", @@ -83,7 +83,7 @@ "eslint-import-resolver-typescript": "^3.6.3", "eslint-plugin-import": "^2.31.0", "fast-glob": "^3.3.2", - "heap-typed": "^1.53.3", + "heap-typed": "^1.53.4", "istanbul-badges-readme": "^1.9.0", "jest": "^29.7.0", "js-sdsl": "^4.4.2", diff --git a/src/data-structures/linked-list/doubly-linked-list.ts b/src/data-structures/linked-list/doubly-linked-list.ts index 9695bed..5cb4dc2 100644 --- a/src/data-structures/linked-list/doubly-linked-list.ts +++ b/src/data-structures/linked-list/doubly-linked-list.ts @@ -819,13 +819,7 @@ export class DoublyLinkedList extends IterableElementBase, newElementOrNode: E | DoublyLinkedListNode ): boolean { - let existingNode; - - if (existingElementOrNode instanceof DoublyLinkedListNode) { - existingNode = existingElementOrNode; - } else { - existingNode = this.getNode(existingElementOrNode); - } + const existingNode: DoublyLinkedListNode | undefined = this.getNode(existingElementOrNode); if (existingNode) { const newNode = this._ensureNode(newElementOrNode); @@ -862,13 +856,7 @@ export class DoublyLinkedList extends IterableElementBase, newElementOrNode: E | DoublyLinkedListNode): boolean { - let existingNode; - - if (existingElementOrNode instanceof DoublyLinkedListNode) { - existingNode = existingElementOrNode; - } else { - existingNode = this.getNode(existingElementOrNode); - } + const existingNode: DoublyLinkedListNode | undefined = this.getNode(existingElementOrNode); if (existingNode) { const newNode = this._ensureNode(newElementOrNode); @@ -978,17 +966,15 @@ export class DoublyLinkedList extends IterableElementBase} elementOrNode - The `elementOrNode` parameter in the - * `indexOf` method can be either an element of type `E` or a `DoublyLinkedListNode` containing an - * element of type `E`. - * @returns The `indexOf` method is returning the index of the element or node in the doubly linked - * list. If the element or node is found in the list, the method returns the index of that element or - * node. If the element or node is not found in the list, the method returns -1. + * This function finds the index of a specified element, node, or predicate in a doubly linked list. + * @param {E | DoublyLinkedListNode | ((node: DoublyLinkedListNode) => boolean)} + * elementNodeOrPredicate - The `indexOf` method takes in a parameter `elementNodeOrPredicate`, which + * can be one of the following: + * @returns The `indexOf` method returns the index of the element in the doubly linked list that + * matches the provided element, node, or predicate. If no match is found, it returns -1. */ - indexOf(elementOrNode: E | DoublyLinkedListNode): number { - const predicate = this._ensurePredicate(elementOrNode); + indexOf(elementNodeOrPredicate: E | DoublyLinkedListNode | ((node: DoublyLinkedListNode) => boolean)): number { + const predicate = this._ensurePredicate(elementNodeOrPredicate); let index = 0; let current = this.head; while (current) { @@ -1005,8 +991,6 @@ export class DoublyLinkedList extends IterableElementBase | ((node: DoublyLinkedListNode) => boolean)} elementNodeOrPredicate @@ -1180,6 +1164,26 @@ export class DoublyLinkedList extends IterableElementBase | ((node: DoublyLinkedListNode) => boolean)): number { + const predicate = this._ensurePredicate(elementOrNode); + let count = 0; + let current = this.head; + + while (current) { + if (predicate(current)) { + count++; + } + current = current.next; + } + + return count; + } + /** * Time Complexity: O(n) * Space Complexity: O(n) diff --git a/src/data-structures/linked-list/singly-linked-list.ts b/src/data-structures/linked-list/singly-linked-list.ts index ca8310f..ef8e437 100644 --- a/src/data-structures/linked-list/singly-linked-list.ts +++ b/src/data-structures/linked-list/singly-linked-list.ts @@ -121,34 +121,17 @@ export class SinglyLinkedList extends IterableElementBase(data: E[]) { - const singlyLinkedList = new SinglyLinkedList(); - for (const item of data) { - singlyLinkedList.push(item); - } - return singlyLinkedList; - } - /** * Time Complexity: O(1) * Space Complexity: O(1) * - * The push function adds a new element to the end of a singly linked list. - * @param {E} element - The "element" parameter represents the value of the element that you want to - * add to the linked list. - * @returns The `push` method is returning a boolean value, `true`. + * The `push` function adds a new element or node to the end of a singly linked list. + * @param {E | SinglyLinkedListNode} elementOrNode - The `elementOrNode` parameter in the `push` + * method can accept either an element of type `E` or a `SinglyLinkedListNode` object. + * @returns The `push` method is returning a boolean value, specifically `true`. */ - push(element: E): boolean { - const newNode = new SinglyLinkedListNode(element); + push(elementOrNode: E | SinglyLinkedListNode): boolean { + const newNode = this._ensureNode(elementOrNode); if (!this.head) { this._head = newNode; this._tail = newNode; @@ -208,13 +191,15 @@ export class SinglyLinkedList extends IterableElementBase} elementOrNode - The `elementOrNode` parameter in the + * `unshift` method can be either an element of type `E` or a `SinglyLinkedListNode` containing an + * element of type `E`. + * @returns The `unshift` method is returning a boolean value, specifically `true`. */ - unshift(element: E): boolean { - const newNode = new SinglyLinkedListNode(element); + unshift(elementOrNode: E | SinglyLinkedListNode): boolean { + const newNode = this._ensureNode(elementOrNode); if (!this.head) { this._head = newNode; this._tail = newNode; @@ -226,6 +211,30 @@ export class SinglyLinkedList extends IterableElementBase | ((node: SinglyLinkedListNode) => boolean)} elementNodeOrPredicate + * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `get` method can be one of + * the following types: + * @returns The `get` method returns the value of the first node in the singly linked list that + * satisfies the provided predicate function. If no such node is found, it returns `undefined`. + */ + get( + elementNodeOrPredicate: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean) + ): E | undefined { + const predicate = this._ensurePredicate(elementNodeOrPredicate); + let current = this.head; + while (current) { + if (predicate(current)) return current.value; + current = current.next; + } + return undefined; + } + /** * Time Complexity: O(n) * Space Complexity: O(1) @@ -245,6 +254,25 @@ export class SinglyLinkedList extends IterableElementBase | ((node: SinglyLinkedListNode) => boolean)} elementNodeOrPredicate + * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `isNode` function can be + * one of the following types: + * @returns The `isNode` function is checking if the `elementNodeOrPredicate` parameter is an + * instance of `SinglyLinkedListNode`. If it is, the function returns `true`, indicating that the + * parameter is a `SinglyLinkedListNode`. If it is not an instance of `SinglyLinkedListNode`, + * the function returns `false`. + */ + isNode( + elementNodeOrPredicate: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean) + ): elementNodeOrPredicate is SinglyLinkedListNode { + return elementNodeOrPredicate instanceof SinglyLinkedListNode; + } + /** * Time Complexity: O(n) * Space Complexity: O(1) @@ -296,18 +324,18 @@ export class SinglyLinkedList extends IterableElementBase} valueOrNode - The `valueOrNode` parameter can accept either a value of type `E` + * @param {E | SinglyLinkedListNode} elementOrNode - The `elementOrNode` parameter can accept either a value of type `E` * or a `SinglyLinkedListNode` object. * @returns The `delete` method returns a boolean value. It returns `true` if the value or node is found and * successfully deleted from the linked list, and `false` if the value or node is not found in the linked list. */ - delete(valueOrNode: E | SinglyLinkedListNode | undefined): boolean { - if (valueOrNode === undefined) return false; + delete(elementOrNode: E | SinglyLinkedListNode | undefined): boolean { + if (elementOrNode === undefined) return false; let value: E; - if (valueOrNode instanceof SinglyLinkedListNode) { - value = valueOrNode.value; + if (elementOrNode instanceof SinglyLinkedListNode) { + value = elementOrNode.value; } else { - value = valueOrNode; + value = elementOrNode; } let current = this.head, prev = undefined; @@ -339,26 +367,30 @@ export class SinglyLinkedList extends IterableElementBase} newElementOrNode - The `newElementOrNode` parameter in the + * `addAt` method can be either a value of type `E` or a `SinglyLinkedListNode` object. This + * parameter represents the element or node that you want to add to the linked list at the specified + * index. + * @returns The `addAt` method returns a boolean value - `true` if the element or node was + * successfully added at the specified index, and `false` if the index is out of bounds. */ - addAt(index: number, value: E): boolean { + addAt(index: number, newElementOrNode: E | SinglyLinkedListNode): boolean { if (index < 0 || index > this._size) return false; + if (index === 0) { - this.unshift(value); + this.unshift(newElementOrNode); return true; } if (index === this._size) { - this.push(value); + this.push(newElementOrNode); return true; } - const newNode = new SinglyLinkedListNode(value); + const newNode = this._ensureNode(newElementOrNode); const prevNode = this.getNodeAt(index - 1); newNode.next = prevNode!.next; prevNode!.next = newNode; @@ -430,17 +462,22 @@ export class SinglyLinkedList extends IterableElementBase | ((node: SinglyLinkedListNode) => boolean)} elementNodeOrPredicate + * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `indexOf` method can be one + * of the following types: + * @returns The `indexOf` method returns the index of the first occurrence of the element that + * matches the provided predicate in the singly linked list. If no matching element is found, it + * returns -1. */ - indexOf(value: E): number { + indexOf(elementNodeOrPredicate: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean)): number { + const predicate = this._ensurePredicate(elementNodeOrPredicate); let index = 0; let current = this.head; while (current) { - if (current.value === value) { + if (predicate(current)) { return index; } index++; @@ -454,17 +491,24 @@ export class SinglyLinkedList extends IterableElementBase` if a node with the specified value is found in the linked list. If no node with - * the specified value is found, the function returns `undefined`. + * The function `getNode` in TypeScript searches for a node in a singly linked list based on a given + * element, node, or predicate. + * @param {E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean) | undefined} elementNodeOrPredicate + * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter in the `getNode` method can be one + * of the following types: + * @returns The `getNode` method returns either a `SinglyLinkedListNode` if a matching node is + * found based on the provided predicate, or it returns `undefined` if no matching node is found or + * if the input parameter is `undefined`. */ - getNode(value: E): SinglyLinkedListNode | undefined { + getNode( + elementNodeOrPredicate: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean) | undefined + ): SinglyLinkedListNode | undefined { + if (elementNodeOrPredicate === undefined) return; + const predicate = this._ensurePredicate(elementNodeOrPredicate); let current = this.head; while (current) { - if (current.value === value) { + if (predicate(current)) { return current; } current = current.next; @@ -477,31 +521,39 @@ export class SinglyLinkedList extends IterableElementBase} existingValueOrNode - The existing value or node that you want to insert the - * new value before. It can be either the value itself or a node containing the value in the linked list. - * @param {E} newValue - The `newValue` parameter represents the value that you want to insert into the linked list. - * @returns The method `addBefore` returns a boolean value. It returns `true` if the new value was successfully - * inserted before the existing value, and `false` otherwise. + * The function `addBefore` in TypeScript adds a new element or node before an existing element or + * node in a singly linked list. + * @param {E | SinglyLinkedListNode} existingElementOrNode - existingElementOrNode represents the + * element or node in the linked list before which you want to add a new element or node. + * @param {E | SinglyLinkedListNode} newElementOrNode - The `newElementOrNode` parameter in the + * `addBefore` method represents the element or node that you want to insert before the existing + * element or node in the linked list. This new element can be of type `E` or a + * `SinglyLinkedListNode`. + * @returns The `addBefore` method returns a boolean value - `true` if the new element or node was + * successfully added before the existing element or node, and `false` if the operation was + * unsuccessful. */ - addBefore(existingValueOrNode: E | SinglyLinkedListNode, newValue: E): boolean { + addBefore( + existingElementOrNode: E | SinglyLinkedListNode, + newElementOrNode: E | SinglyLinkedListNode + ): boolean { if (!this.head) return false; let existingValue: E; - if (existingValueOrNode instanceof SinglyLinkedListNode) { - existingValue = existingValueOrNode.value; + if (this.isNode(existingElementOrNode)) { + existingValue = existingElementOrNode.value; } else { - existingValue = existingValueOrNode; + existingValue = existingElementOrNode; } if (this.head.value === existingValue) { - this.unshift(newValue); + this.unshift(newElementOrNode); return true; } let current = this.head; while (current.next) { if (current.next.value === existingValue) { - const newNode = new SinglyLinkedListNode(newValue); + const newNode = this._ensureNode(newElementOrNode); newNode.next = current.next; current.next = newNode; this._size++; @@ -517,24 +569,23 @@ export class SinglyLinkedList extends IterableElementBase} existingValueOrNode - The existing value or node in the linked list after which - * the new value will be inserted. It can be either the value of the existing node or the existing node itself. - * @param {E} newValue - The value that you want to insert into the linked list after the existing value or node. - * @returns The method returns a boolean value. It returns true if the new value was successfully inserted after the - * existing value or node, and false if the existing value or node was not found in the linked list. + * The `addAfter` function in TypeScript adds a new element or node after an existing element or node + * in a singly linked list. + * @param {E | SinglyLinkedListNode} existingElementOrNode - existingElementOrNode can be either + * an element of type E or a SinglyLinkedListNode of type E. + * @param {E | SinglyLinkedListNode} newElementOrNode - The `newElementOrNode` parameter in the + * `addAfter` method represents the element or node that you want to add after the existing element + * or node in a singly linked list. This parameter can be either the value of the new element or a + * reference to a `SinglyLinkedListNode` containing + * @returns The `addAfter` method returns a boolean value - `true` if the new element or node was + * successfully added after the existing element or node, and `false` if the existing element or node + * was not found. */ - addAfter(existingValueOrNode: E | SinglyLinkedListNode, newValue: E): boolean { - let existingNode: E | SinglyLinkedListNode | undefined; - - if (existingValueOrNode instanceof SinglyLinkedListNode) { - existingNode = existingValueOrNode; - } else { - existingNode = this.getNode(existingValueOrNode); - } + addAfter(existingElementOrNode: E | SinglyLinkedListNode, newElementOrNode: E | SinglyLinkedListNode): boolean { + const existingNode: SinglyLinkedListNode | undefined = this.getNode(existingElementOrNode); if (existingNode) { - const newNode = new SinglyLinkedListNode(newValue); + const newNode = this._ensureNode(newElementOrNode); newNode.next = existingNode.next; existingNode.next = newNode; if (existingNode === this.tail) { @@ -551,16 +602,20 @@ export class SinglyLinkedList extends IterableElementBase | ((node: SinglyLinkedListNode) => boolean)} elementOrNode + * - The `elementOrNode` parameter in the `countOccurrences` method can accept three types of values: + * @returns The `countOccurrences` method returns the number of occurrences of the specified element, + * node, or predicate function in the singly linked list. */ - countOccurrences(value: E): number { + countOccurrences(elementOrNode: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean)): number { + const predicate = this._ensurePredicate(elementOrNode); let count = 0; let current = this.head; while (current) { - if (current.value === value) { + if (predicate(current)) { count++; } current = current.next; @@ -657,4 +712,70 @@ export class SinglyLinkedList extends IterableElementBase(data: E[]) { + const singlyLinkedList = new SinglyLinkedList(); + for (const item of data) { + singlyLinkedList.push(item); + } + return singlyLinkedList; + } + + /** + * The _isPredicate function in TypeScript checks if the input is a function that takes a + * SinglyLinkedListNode as an argument and returns a boolean. + * @param {E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean)} elementNodeOrPredicate + * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types: + * @returns The _isPredicate method is returning a boolean value based on whether the + * elementNodeOrPredicate parameter is a function or not. If the elementNodeOrPredicate is a + * function, the method will return true, indicating that it is a predicate function. If it is not a + * function, the method will return false. + */ + protected _isPredicate( + elementNodeOrPredicate: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean) + ): elementNodeOrPredicate is (node: SinglyLinkedListNode) => boolean { + return typeof elementNodeOrPredicate === 'function'; + } + + /** + * The function `_ensureNode` ensures that the input is a valid node and returns it, creating a new + * node if necessary. + * @param {E | SinglyLinkedListNode} elementOrNode - The `elementOrNode` parameter can be either + * an element of type `E` or a `SinglyLinkedListNode` containing an element of type `E`. + * @returns A SinglyLinkedListNode object is being returned. + */ + protected _ensureNode(elementOrNode: E | SinglyLinkedListNode) { + if (this.isNode(elementOrNode)) return elementOrNode; + + return new SinglyLinkedListNode(elementOrNode); + } + + /** + * The function `_ensurePredicate` in TypeScript ensures that the input is either a node, a predicate + * function, or a value to compare with the node's value. + * @param {E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean)} elementNodeOrPredicate + * elementNodeOrPredicate - The `elementNodeOrPredicate` parameter can be one of the following types: + * @returns A function is being returned. If the input `elementNodeOrPredicate` is already a node, a + * function is returned that checks if a given node is equal to the input node. If the input is a + * predicate function, it is returned as is. If the input is neither a node nor a predicate function, + * a function is returned that checks if a given node's value is equal to the input + */ + protected _ensurePredicate( + elementNodeOrPredicate: E | SinglyLinkedListNode | ((node: SinglyLinkedListNode) => boolean) + ) { + if (this.isNode(elementNodeOrPredicate)) return (node: SinglyLinkedListNode) => node === elementNodeOrPredicate; + + if (this._isPredicate(elementNodeOrPredicate)) return elementNodeOrPredicate; + + return (node: SinglyLinkedListNode) => node.value === elementNodeOrPredicate; + } }