mirror of
https://github.com/zrwusa/data-structure-typed.git
synced 2024-11-23 12:54:04 +00:00
refactor: Extract all methods such as 'some', 'every', 'entries', 'keys', 'values', 'forEach', 'reduce' into the base classes 'IterableElementBase' and 'IterablePairBase'.
This commit is contained in:
parent
40abf9a8c2
commit
7f5eb6cb70
|
@ -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.48.0](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
## [v1.48.1](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming)
|
||||
|
||||
### Changes
|
||||
|
||||
|
|
1
src/data-structures/base/index.ts
Normal file
1
src/data-structures/base/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './iterable-base';
|
329
src/data-structures/base/iterable-base.ts
Normal file
329
src/data-structures/base/iterable-base.ts
Normal file
|
@ -0,0 +1,329 @@
|
|||
import { ElementCallback, PairCallback, ReduceElementCallback, ReducePairCallback } from "../../types";
|
||||
|
||||
export abstract class IterablePairBase<K = any, V = any> {
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function is an implementation of the Symbol.iterator method that returns an iterable iterator.
|
||||
* @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It
|
||||
* allows the function to accept any number of arguments as an array. In this case, the `args`
|
||||
* parameter is used to pass any additional arguments to the `_getIterator` method.
|
||||
*/
|
||||
* [Symbol.iterator](...args: any[]): IterableIterator<[K, V]> {
|
||||
yield* this._getIterator(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The function returns an iterator that yields key-value pairs from the object, where the value can
|
||||
* be undefined.
|
||||
*/
|
||||
* entries(): IterableIterator<[K, V | undefined]> {
|
||||
for (const item of this) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The function returns an iterator that yields the keys of a data structure.
|
||||
*/
|
||||
* keys(): IterableIterator<K> {
|
||||
for (const item of this) {
|
||||
yield item[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The function returns an iterator that yields the values of a collection.
|
||||
*/
|
||||
* values(): IterableIterator<V> {
|
||||
for (const item of this) {
|
||||
yield item[1];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `every` function checks if every element in a collection satisfies a given condition.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is
|
||||
* met for the current element in the iteration.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the first argument to the `predicate` function. If `thisArg` is not provided
|
||||
* @returns The `every` method is returning a boolean value. It returns `true` if every element in
|
||||
* the collection satisfies the provided predicate function, and `false` otherwise.
|
||||
*/
|
||||
every(predicate: PairCallback<K, V, boolean>, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (!predicate.call(thisArg, item[1], item[0], index++, this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The "some" function iterates over a collection and returns true if at least one element satisfies
|
||||
* a given predicate.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* `value`, `key`, and `index`. It should return a boolean value indicating whether the condition is
|
||||
* met for the current element in the iteration.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
|
||||
* it will be passed as the first argument to the `predicate` function. If `thisArg` is
|
||||
* @returns a boolean value. It returns true if the predicate function returns true for any pair in
|
||||
* the collection, and false otherwise.
|
||||
*/
|
||||
some(predicate: PairCallback<K, V, boolean>, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (predicate.call(thisArg, item[1], item[0], index++, this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each key-value pair in a collection and executes a callback
|
||||
* function for each pair.
|
||||
* @param callbackfn - The callback function that will be called for each element in the collection.
|
||||
* It takes four parameters: the value of the current element, the key of the current element, the
|
||||
* index of the current element, and the collection itself.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the callback function. If `thisArg` is provided, it will be
|
||||
* used as the `this` value when calling the callback function. If `thisArg` is not provided, `
|
||||
*/
|
||||
forEach(callbackfn: PairCallback<K, V, void>, thisArg?: any): void {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
const [key, value] = item;
|
||||
callbackfn.call(thisArg, value, key, index++, this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `reduce` function iterates over key-value pairs and applies a callback function to each pair,
|
||||
* accumulating a single value.
|
||||
* @param callbackfn - The callback function that will be called for each element in the collection.
|
||||
* It takes four arguments: the current accumulator value, the current value of the element, the key
|
||||
* of the element, and the index of the element in the collection. It should return the updated
|
||||
* accumulator value.
|
||||
* @param {U} initialValue - The `initialValue` parameter is the initial value of the accumulator. It
|
||||
* is the value that will be used as the first argument to the `callbackfn` function when reducing
|
||||
* the elements of the collection.
|
||||
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
||||
* all the elements in the collection.
|
||||
*/
|
||||
reduce<U>(callbackfn: ReducePairCallback<K, V, U>, initialValue: U): U {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
const [key, value] = item;
|
||||
accumulator = callbackfn(accumulator, value, key, index++, this)
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
protected abstract _getIterator(...args: any[]): IterableIterator<[K, V]>;
|
||||
}
|
||||
|
||||
export abstract class IterableElementBase<V> {
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The function is an implementation of the Symbol.iterator method that returns an IterableIterator.
|
||||
* @param {any[]} args - The `args` parameter in the code snippet represents a rest parameter. It
|
||||
* allows the function to accept any number of arguments as an array. In this case, the `args`
|
||||
* parameter is used to pass any number of arguments to the `_getIterator` method.
|
||||
*/
|
||||
* [Symbol.iterator](...args: any[]): IterableIterator<V> {
|
||||
yield* this._getIterator(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The function returns an iterator that yields all the values in the object.
|
||||
*/
|
||||
* values(): IterableIterator<V> {
|
||||
for (const item of this) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `every` function checks if every element in the array satisfies a given predicate.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* the current element being processed, its index, and the array it belongs to. It should return a
|
||||
* boolean value indicating whether the element satisfies a certain condition or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
||||
* @returns The `every` method is returning a boolean value. It returns `true` if every element in
|
||||
* the array satisfies the provided predicate function, and `false` otherwise.
|
||||
*/
|
||||
every(predicate: ElementCallback<V, boolean>, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (!predicate.call(thisArg, item as V, index++, this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The "some" function checks if at least one element in a collection satisfies a given predicate.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* `value`, `index`, and `array`. It should return a boolean value indicating whether the current
|
||||
* element satisfies the condition.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
|
||||
* it will be passed as the `this` value to the `predicate` function. If `thisArg
|
||||
* @returns a boolean value. It returns true if the predicate function returns true for any element
|
||||
* in the collection, and false otherwise.
|
||||
*/
|
||||
some(predicate: ElementCallback<V, boolean>, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
if (predicate.call(thisArg, item as V, index++, this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each element in an array-like object and calls a callback
|
||||
* function for each element.
|
||||
* @param callbackfn - The callbackfn parameter is a function that will be called for each element in
|
||||
* the array. It takes three arguments: the current element being processed, the index of the current
|
||||
* element, and the array that forEach was called upon.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
||||
* be passed as the `this` value to the `callbackfn` function. If `thisArg
|
||||
*/
|
||||
forEach(callbackfn: ElementCallback<V, void>, thisArg?: any): void {
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
callbackfn.call(thisArg, item as V, index++, this)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `reduce` function iterates over the elements of an array-like object and applies a callback
|
||||
* function to reduce them into a single value.
|
||||
* @param callbackfn - The callbackfn parameter is a function that will be called for each element in
|
||||
* the array. It takes four arguments:
|
||||
* @param {U} initialValue - The initialValue parameter is the initial value of the accumulator. It
|
||||
* is the value that the accumulator starts with before the reduction operation begins.
|
||||
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
||||
* all the elements in the array and applying the callback function to each element.
|
||||
*/
|
||||
reduce<U>(callbackfn: ReduceElementCallback<V, U>, initialValue: U): U {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const item of this) {
|
||||
accumulator = callbackfn(accumulator, item as V, index++, this)
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
protected abstract _getIterator(...args: any[]): IterableIterator<V>;
|
||||
}
|
|
@ -13,7 +13,7 @@ import type {
|
|||
BTNKey,
|
||||
BTNodeEntry,
|
||||
BTNodeExemplar,
|
||||
BTNodeKeyOrNode
|
||||
BTNodeKeyOrNode,
|
||||
} from '../../types';
|
||||
import {
|
||||
BinaryTreeNested,
|
||||
|
@ -22,11 +22,13 @@ import {
|
|||
DFSOrderPattern,
|
||||
FamilyPosition,
|
||||
IterationType,
|
||||
NodeDisplayLayout
|
||||
NodeDisplayLayout,
|
||||
PairCallback
|
||||
} from '../../types';
|
||||
import { IBinaryTree } from '../../interfaces';
|
||||
import { trampoline } from '../../utils';
|
||||
import { Queue } from '../queue';
|
||||
import { IterablePairBase } from "../base";
|
||||
|
||||
/**
|
||||
* Represents a node in a binary tree.
|
||||
|
@ -103,7 +105,7 @@ export class BinaryTreeNode<V = any, N extends BinaryTreeNode<V, N> = BinaryTree
|
|||
* 9. Complete Trees: All levels are fully filled except possibly the last, filled from left to right.
|
||||
*/
|
||||
|
||||
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>>
|
||||
export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode<V, BinaryTreeNodeNested<V>>, TREE extends BinaryTree<V, N, TREE> = BinaryTree<V, N, BinaryTreeNested<V, N>>> extends IterablePairBase<BTNKey, V | undefined>
|
||||
|
||||
implements IBinaryTree<V, N, TREE> {
|
||||
iterationType = IterationType.ITERATIVE
|
||||
|
@ -118,7 +120,7 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
* required.
|
||||
*/
|
||||
constructor(elements?: Iterable<BTNodeExemplar<V, N>>, options?: Partial<BinaryTreeOptions>) {
|
||||
|
||||
super();
|
||||
if (options) {
|
||||
const { iterationType } = options;
|
||||
if (iterationType) {
|
||||
|
@ -1724,47 +1726,6 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
return ans;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(n)
|
||||
*
|
||||
* The function "keys" returns an array of keys from a given object.
|
||||
* @returns an array of BTNKey objects.
|
||||
*/
|
||||
keys(): BTNKey[] {
|
||||
const keys: BTNKey[] = [];
|
||||
for (const entry of this) {
|
||||
keys.push(entry[0]);
|
||||
}
|
||||
return keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(n)
|
||||
*
|
||||
* The function "values" returns an array of values from a map-like object.
|
||||
* @returns The `values()` method is returning an array of values (`V`) from the entries in the
|
||||
* object.
|
||||
*/
|
||||
values(): (V | undefined)[] {
|
||||
const values: (V | undefined)[] = [];
|
||||
for (const entry of this) {
|
||||
values.push(entry[1]);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(n)
|
||||
|
@ -1785,34 +1746,30 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
}
|
||||
|
||||
/**
|
||||
* Time complexity: O(n)
|
||||
* Space complexity: O(1)
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* The `forEach` function iterates over each entry in a tree and calls a callback function with the
|
||||
* entry and the tree as arguments.
|
||||
* @param callback - The callback parameter is a function that will be called for each entry in the
|
||||
* tree. It takes two parameters: entry and tree.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new tree by iterating over the elements of the current tree and
|
||||
* adding only the elements that satisfy the given predicate function.
|
||||
* @param predicate - The `predicate` parameter is a function that takes three arguments: `value`,
|
||||
* `key`, and `index`. It should return a boolean value indicating whether the pair should be
|
||||
* included in the filtered tree or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as the `this` value when executing the `predicate` function. If `thisArg` is provided,
|
||||
* it will be passed as the first argument to the `predicate` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new tree object that contains the key-value pairs that
|
||||
* pass the given predicate function.
|
||||
*/
|
||||
forEach(callback: (entry: [BTNKey, V | undefined], tree: this) => void): void {
|
||||
for (const entry of this) {
|
||||
callback(entry, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `filter` function creates a new tree by iterating over the entries of the current tree and
|
||||
* adding the entries that satisfy the given predicate.
|
||||
* @param predicate - The `predicate` parameter is a function that takes two arguments: `entry` and
|
||||
* `tree`.
|
||||
* @returns The `filter` method is returning a new tree object that contains only the entries that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: (entry: [BTNKey, V | undefined], tree: this) => boolean) {
|
||||
filter(predicate: PairCallback<BTNKey, V | undefined, boolean>, thisArg?: any) {
|
||||
const newTree = this.createTree();
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
if (predicate([key, value], this)) {
|
||||
if (predicate.call(thisArg, value, key, index++, this)) {
|
||||
newTree.add([key, value]);
|
||||
}
|
||||
}
|
||||
|
@ -1820,87 +1777,43 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
}
|
||||
|
||||
/**
|
||||
* The `map` function creates a new tree by applying a callback function to each entry in the current
|
||||
* tree.
|
||||
* @param callback - The callback parameter is a function that takes two arguments: entry and tree.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function creates a new tree by applying a callback function to each key-value pair in
|
||||
* the original tree.
|
||||
* @param callback - The callback parameter is a function that will be called for each key-value pair
|
||||
* in the tree. It takes four arguments: the value of the current pair, the key of the current pair,
|
||||
* the index of the current pair, and a reference to the tree itself. The callback function should
|
||||
* return a new
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the callback function. If you pass a value for `thisArg`, it
|
||||
* will be used as the `this` value when the callback function is called. If you don't pass a value
|
||||
* @returns The `map` method is returning a new tree object.
|
||||
*/
|
||||
map(callback: (entry: [BTNKey, V | undefined], tree: this) => V) {
|
||||
map(callback: PairCallback<BTNKey, V | undefined, V>, thisArg?: any) {
|
||||
const newTree = this.createTree();
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
newTree.add([key, callback([key, value], this)]);
|
||||
newTree.add([key, callback.call(thisArg, value, key, index++, this)]);
|
||||
}
|
||||
return newTree;
|
||||
}
|
||||
|
||||
// TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
||||
// map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
|
||||
// const newTree = this.createTree();
|
||||
// for (const [key, value] of this) {
|
||||
// newTree.add(key, callback([key, value], this));
|
||||
// }
|
||||
// return newTree;
|
||||
// }
|
||||
|
||||
/**
|
||||
* The `reduce` function iterates over the entries of a tree and applies a callback function to each
|
||||
* entry, accumulating a single value.
|
||||
* @param callback - The callback parameter is a function that takes three arguments: accumulator,
|
||||
* entry, and tree. It is called for each entry in the tree and is used to accumulate a single value
|
||||
* based on the logic defined in the callback function.
|
||||
* @param {T} initialValue - The initialValue parameter is the initial value of the accumulator. It
|
||||
* is the value that will be passed as the first argument to the callback function when reducing the
|
||||
* elements of the tree.
|
||||
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
||||
* all the entries in the tree and applying the callback function to each entry.
|
||||
*/
|
||||
reduce<T>(callback: (accumulator: T, entry: [BTNKey, V | undefined], tree: this) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
for (const [key, value] of this) {
|
||||
accumulator = callback(accumulator, [key, value], this);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* The above function is an iterator for a binary tree that can be used to traverse the tree in
|
||||
* either an iterative or recursive manner.
|
||||
* @param node - The `node` parameter represents the current node in the binary tree from which the
|
||||
* iteration starts. It is an optional parameter with a default value of `this.root`, which means
|
||||
* that if no node is provided, the iteration will start from the root of the binary tree.
|
||||
* @returns The `*[Symbol.iterator]` method returns a generator object that yields the keys of the
|
||||
* binary tree nodes in a specific order.
|
||||
*/
|
||||
* [Symbol.iterator](node = this.root): Generator<[BTNKey, V | undefined], void, undefined> {
|
||||
if (!node) return;
|
||||
|
||||
if (this.iterationType === IterationType.ITERATIVE) {
|
||||
const stack: (N | null | undefined)[] = [];
|
||||
let current: N | null | undefined = node;
|
||||
|
||||
while (current || stack.length > 0) {
|
||||
while (current && !isNaN(current.key)) {
|
||||
stack.push(current);
|
||||
current = current.left;
|
||||
}
|
||||
|
||||
current = stack.pop();
|
||||
|
||||
if (current && !isNaN(current.key)) {
|
||||
yield [current.key, current.value];
|
||||
current = current.right;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node.left && !isNaN(node.key)) {
|
||||
yield* this[Symbol.iterator](node.left);
|
||||
}
|
||||
yield [node.key, node.value];
|
||||
if (node.right && !isNaN(node.key)) {
|
||||
yield* this[Symbol.iterator](node.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
// // TODO Type error, need to return a TREE<NV> that is a value type only for callback function.
|
||||
// // map<NV>(callback: (entry: [BTNKey, V | undefined], tree: this) => NV) {
|
||||
// // const newTree = this.createTree();
|
||||
// // for (const [key, value] of this) {
|
||||
// // newTree.add(key, callback([key, value], this));
|
||||
// // }
|
||||
// // return newTree;
|
||||
// // }
|
||||
//
|
||||
|
||||
/**
|
||||
* The `print` function is used to display a binary tree structure in a visually appealing way.
|
||||
|
@ -1931,6 +1844,37 @@ export class BinaryTree<V = any, N extends BinaryTreeNode<V, N> = BinaryTreeNode
|
|||
display(beginRoot);
|
||||
}
|
||||
|
||||
protected* _getIterator(node = this.root): IterableIterator<[BTNKey, V | undefined]> {
|
||||
if (!node) return;
|
||||
|
||||
if (this.iterationType === IterationType.ITERATIVE) {
|
||||
const stack: (N | null | undefined)[] = [];
|
||||
let current: N | null | undefined = node;
|
||||
|
||||
while (current || stack.length > 0) {
|
||||
while (current && !isNaN(current.key)) {
|
||||
stack.push(current);
|
||||
current = current.left;
|
||||
}
|
||||
|
||||
current = stack.pop();
|
||||
|
||||
if (current && !isNaN(current.key)) {
|
||||
yield [current.key, current.value];
|
||||
current = current.right;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (node.left && !isNaN(node.key)) {
|
||||
yield* this[Symbol.iterator](node.left);
|
||||
}
|
||||
yield [node.key, node.value];
|
||||
if (node.right && !isNaN(node.key)) {
|
||||
yield* this[Symbol.iterator](node.right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected _displayAux(node: N | null | undefined, options: BinaryTreePrintOptions): NodeDisplayLayout {
|
||||
const { isShowNull, isShowUndefined, isShowRedBlackNIL } = options;
|
||||
const emptyDisplayLayout = <NodeDisplayLayout>[['─'], 1, 0, 0];
|
||||
|
|
|
@ -8,8 +8,10 @@
|
|||
import { uuidV4 } from '../../utils';
|
||||
import { PriorityQueue } from '../priority-queue';
|
||||
import type { DijkstraResult, VertexKey } from '../../types';
|
||||
import { PairCallback } from "../../types";
|
||||
import { IGraph } from '../../interfaces';
|
||||
import { Queue } from '../queue';
|
||||
import { IterablePairBase } from "../base";
|
||||
|
||||
export abstract class AbstractVertex<V = any> {
|
||||
key: VertexKey;
|
||||
|
@ -64,7 +66,11 @@ export abstract class AbstractGraph<
|
|||
E = any,
|
||||
VO extends AbstractVertex<V> = AbstractVertex<V>,
|
||||
EO extends AbstractEdge<E> = AbstractEdge<E>
|
||||
> implements IGraph<V, E, VO, EO> {
|
||||
> extends IterablePairBase<VertexKey, V | undefined> implements IGraph<V, E, VO, EO> {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected _vertices: Map<VertexKey, VO> = new Map<VertexKey, VO>();
|
||||
|
||||
get vertices(): Map<VertexKey, VO> {
|
||||
|
@ -1159,50 +1165,71 @@ export abstract class AbstractGraph<
|
|||
return this.tarjan(false, true, false, false).bridges;
|
||||
}
|
||||
|
||||
* [Symbol.iterator](): Iterator<[VertexKey, V | undefined]> {
|
||||
for (const vertex of this._vertices.values()) {
|
||||
yield [vertex.key, vertex.value];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
forEach(callback: (entry: [VertexKey, V | undefined], index: number, map: Map<VertexKey, VO>) => void): void {
|
||||
let index = 0;
|
||||
for (const vertex of this) {
|
||||
callback(vertex, index, this._vertices);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
filter(predicate: (entry: [VertexKey, V | undefined], index: number, map: Map<VertexKey, VO>) => boolean): [VertexKey, V | undefined][] {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function iterates over key-value pairs in a data structure and returns an array of
|
||||
* pairs that satisfy a given predicate.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes four arguments:
|
||||
* `value`, `key`, `index`, and `this`. It is used to determine whether an element should be included
|
||||
* in the filtered array. The callback function should return `true` if the element should be
|
||||
* included, and `
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the `predicate` function. It is used when you want to bind a
|
||||
* specific object as the context for the `predicate` function. If `thisArg` is provided, it will be
|
||||
* @returns The `filter` method returns an array of key-value pairs `[VertexKey, V | undefined][]`
|
||||
* that satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: PairCallback<VertexKey, V | undefined, boolean>, thisArg?: any): [VertexKey, V | undefined][] {
|
||||
const filtered: [VertexKey, V | undefined][] = [];
|
||||
let index = 0;
|
||||
for (const entry of this) {
|
||||
if (predicate(entry, index, this._vertices)) {
|
||||
filtered.push(entry);
|
||||
for (const [key, value] of this) {
|
||||
if (predicate.call(thisArg, value, key, index, this)) {
|
||||
filtered.push([key, value]);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return filtered;
|
||||
}
|
||||
|
||||
map<T>(callback: (entry: [VertexKey, V | undefined], index: number, map: Map<VertexKey, VO>) => T): T[] {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function iterates over the elements of a collection and applies a callback function to
|
||||
* each element, returning an array of the results.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* map. It takes four arguments:
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the callback function. If `thisArg` is provided, it will be
|
||||
* used as the `this` value when calling the callback function. If `thisArg` is not provided, `
|
||||
* @returns The `map` function is returning an array of type `T[]`.
|
||||
*/
|
||||
map<T>(callback: PairCallback<VertexKey, V | undefined, T>, thisArg?: any): T[] {
|
||||
const mapped: T[] = [];
|
||||
let index = 0;
|
||||
for (const entry of this) {
|
||||
mapped.push(callback(entry, index, this._vertices));
|
||||
for (const [key, value] of this) {
|
||||
mapped.push(callback.call(thisArg, value, key, index, this));
|
||||
index++;
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
|
||||
reduce<T>(callback: (accumulator: T, entry: [VertexKey, V | undefined], index: number, map: Map<VertexKey, VO>) => T, initialValue: T): T {
|
||||
let accumulator: T = initialValue;
|
||||
let index = 0;
|
||||
for (const entry of this) {
|
||||
accumulator = callback(accumulator, entry, index, this._vertices);
|
||||
index++;
|
||||
protected* _getIterator(): IterableIterator<[VertexKey, V | undefined]> {
|
||||
for (const vertex of this._vertices.values()) {
|
||||
yield [vertex.key, vertex.value];
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
protected abstract _addEdgeOnly(edge: EO): boolean;
|
||||
|
|
|
@ -7,9 +7,10 @@
|
|||
*/
|
||||
|
||||
import { isWeakKey, rangeCheck } from '../../utils';
|
||||
import { HashMapLinkedNode, HashMapOptions, HashMapStoreItem } from '../../types';
|
||||
import { HashMapLinkedNode, HashMapOptions, HashMapStoreItem, PairCallback } from '../../types';
|
||||
import { IterablePairBase } from "../base";
|
||||
|
||||
export class HashMap<K = any, V = any> {
|
||||
export class HashMap<K = any, V = any> extends IterablePairBase<K, V> {
|
||||
protected _store: { [key: string]: HashMapStoreItem<K, V> } = {};
|
||||
protected _objMap: Map<object, V> = new Map();
|
||||
|
||||
|
@ -24,6 +25,7 @@ export class HashMap<K = any, V = any> {
|
|||
constructor(elements: Iterable<[K, V]> = [], options?: {
|
||||
hashFn: (key: K) => string
|
||||
}) {
|
||||
super();
|
||||
if (options) {
|
||||
const { hashFn } = options;
|
||||
if (hashFn) {
|
||||
|
@ -145,102 +147,14 @@ export class HashMap<K = any, V = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that yields key-value pairs from both an object store and an
|
||||
* object map.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
* [Symbol.iterator](): IterableIterator<[K, V]> {
|
||||
for (const node of Object.values(this._store)) {
|
||||
yield [node.key, node.value] as [K, V];
|
||||
}
|
||||
for (const node of this._objMap) {
|
||||
yield node as [K, V];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that yields key-value pairs from the object.
|
||||
*/
|
||||
* entries(): IterableIterator<[K, V]> {
|
||||
for (const item of this) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The function `keys()` returns an iterator that yields all the keys of the object.
|
||||
*/
|
||||
* keys(): IterableIterator<K> {
|
||||
for (const [key] of this) {
|
||||
yield key;
|
||||
}
|
||||
}
|
||||
|
||||
* values(): IterableIterator<V> {
|
||||
for (const [, value] of this) {
|
||||
yield value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `every` function checks if every element in a HashMap satisfies a given predicate function.
|
||||
* @param predicate - The predicate parameter is a function that takes four arguments: value, key,
|
||||
* index, and map. It is used to test each element in the map against a condition. If the predicate
|
||||
* function returns false for any element, the every() method will return false. If the predicate
|
||||
* function returns true for all
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
||||
* @returns The method is returning a boolean value. It returns true if the predicate function
|
||||
* returns true for every element in the map, and false otherwise.
|
||||
*/
|
||||
every(predicate: (value: V, key: K, index: number, map: HashMap<K, V>) => boolean, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
if (!predicate.call(thisArg, value, key, index++, this)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "some" function checks if at least one element in a HashMap satisfies a given predicate.
|
||||
* @param predicate - The `predicate` parameter is a function that takes four arguments: `value`,
|
||||
* `key`, `index`, and `map`. It is used to determine whether a specific condition is met for a given
|
||||
* key-value pair in the `HashMap`.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
||||
* @returns a boolean value. It returns true if the predicate function returns true for any element
|
||||
* in the map, and false otherwise.
|
||||
*/
|
||||
some(predicate: (value: V, key: K, index: number, map: HashMap<K, V>) => boolean, thisArg?: any): boolean {
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
if (predicate.call(thisArg, value, key, index++, this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `forEach` function iterates over the elements of a HashMap and applies a callback function to
|
||||
* each element.
|
||||
* @param callbackfn - A function that will be called for each key-value pair in the HashMap. It
|
||||
* takes four parameters:
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callbackfn` function. If `thisArg` is provided, it will
|
||||
* be passed as the `this` value inside the `callbackfn` function. If `thisArg
|
||||
*/
|
||||
forEach(callbackfn: (value: V, key: K, index: number, map: HashMap<K, V>) => void, thisArg?: any): void {
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
callbackfn.call(thisArg, value, key, index++, this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function in TypeScript creates a new HashMap by applying a callback function to each
|
||||
* key-value pair in the original HashMap.
|
||||
* @param callbackfn - The callback function that will be called for each key-value pair in the
|
||||
|
@ -251,7 +165,7 @@ export class HashMap<K = any, V = any> {
|
|||
* @returns The `map` method is returning a new `HashMap` object with the transformed values based on
|
||||
* the provided callback function.
|
||||
*/
|
||||
map<U>(callbackfn: (value: V, key: K, index: number, map: HashMap<K, V>) => U, thisArg?: any): HashMap<K, U> {
|
||||
map<U>(callbackfn: PairCallback<K, V, U>, thisArg?: any): HashMap<K, U> {
|
||||
const resultMap = new HashMap<K, U>();
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
|
@ -261,6 +175,14 @@ export class HashMap<K = any, V = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new HashMap containing key-value pairs from the original HashMap
|
||||
* that satisfy a given predicate function.
|
||||
* @param predicate - The predicate parameter is a function that takes four arguments: value, key,
|
||||
|
@ -273,7 +195,7 @@ export class HashMap<K = any, V = any> {
|
|||
* @returns The `filter` method is returning a new `HashMap` object that contains the key-value pairs
|
||||
* from the original `HashMap` that pass the provided `predicate` function.
|
||||
*/
|
||||
filter(predicate: (value: V, key: K, index: number, map: HashMap<K, V>) => boolean, thisArg?: any): HashMap<K, V> {
|
||||
filter(predicate: PairCallback<K, V, boolean>, thisArg?: any): HashMap<K, V> {
|
||||
const filteredMap = new HashMap<K, V>();
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
|
@ -284,28 +206,21 @@ export class HashMap<K = any, V = any> {
|
|||
return filteredMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `reduce` function iterates over the elements of a HashMap and applies a callback function to
|
||||
* each element, accumulating a single value.
|
||||
* @param callbackfn - The callback function that will be called for each element in the HashMap. It
|
||||
* takes five parameters:
|
||||
* @param {U} initialValue - The initialValue parameter is the initial value of the accumulator. It
|
||||
* is the value that will be used as the first argument of the callback function when reducing the
|
||||
* elements of the map.
|
||||
* @returns The `reduce` method is returning the final value of the accumulator after iterating over
|
||||
* all the elements in the `HashMap`.
|
||||
*/
|
||||
reduce<U>(callbackfn: (accumulator: U, currentValue: V, currentKey: K, index: number, map: HashMap<K, V>) => U, initialValue: U): U {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
accumulator = callbackfn(accumulator, value, key, index++, this);
|
||||
}
|
||||
return accumulator;
|
||||
print(): void {
|
||||
console.log([...this.entries()]);
|
||||
}
|
||||
|
||||
print(): void{
|
||||
console.log([...this.entries()]);
|
||||
/**
|
||||
* The function returns an iterator that yields key-value pairs from both an object store and an
|
||||
* object map.
|
||||
*/
|
||||
protected* _getIterator(): IterableIterator<[K, V]> {
|
||||
for (const node of Object.values(this._store)) {
|
||||
yield [node.key, node.value] as [K, V];
|
||||
}
|
||||
for (const node of this._objMap) {
|
||||
yield node as [K, V];
|
||||
}
|
||||
}
|
||||
|
||||
protected _hashFn: (key: K) => string = (key: K) => String(key);
|
||||
|
@ -333,7 +248,7 @@ export class HashMap<K = any, V = any> {
|
|||
}
|
||||
}
|
||||
|
||||
export class LinkedHashMap<K = any, V = any> {
|
||||
export class LinkedHashMap<K = any, V = any> extends IterablePairBase<K, V> {
|
||||
|
||||
protected _noObjMap: Record<string, HashMapLinkedNode<K, V | undefined>> = {};
|
||||
protected _objMap = new WeakMap<object, HashMapLinkedNode<K, V | undefined>>();
|
||||
|
@ -349,6 +264,7 @@ export class LinkedHashMap<K = any, V = any> {
|
|||
hashFn: (key: K) => String(key),
|
||||
objHashFn: (key: K) => (<object>key)
|
||||
}) {
|
||||
super();
|
||||
this._sentinel = <HashMapLinkedNode<K, V>>{};
|
||||
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
|
||||
|
||||
|
@ -492,18 +408,6 @@ export class LinkedHashMap<K = any, V = any> {
|
|||
}
|
||||
}
|
||||
|
||||
keys(): K[] {
|
||||
const keys: K[] = [];
|
||||
for (const [key] of this) keys.push(key);
|
||||
return keys;
|
||||
}
|
||||
|
||||
values(): V[] {
|
||||
const values: V[] = [];
|
||||
for (const [, value] of this) values.push(value);
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -644,36 +548,30 @@ export class LinkedHashMap<K = any, V = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the LinkedHashMap.
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each element in a LinkedHashMap and executes a callback function on
|
||||
* each element.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* LinkedHashMap. It takes three arguments:
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
forEach(callback: (element: [K, V], index: number, hashMap: LinkedHashMap<K, V>) => void) {
|
||||
let index = 0;
|
||||
let node = this._head;
|
||||
while (node !== this._sentinel) {
|
||||
callback(<[K, V]>[node.key, node.value], index++, this);
|
||||
node = node.next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `filter` function takes a predicate function and returns a new LinkedHashMap containing only the
|
||||
* key-value pairs that satisfy the predicate.
|
||||
* @param predicate - The `predicate` parameter is a function that takes two arguments: `element` and
|
||||
* `map`.
|
||||
* @returns a new LinkedHashMap object that contains the key-value pairs from the original LinkedHashMap that
|
||||
* satisfy the given predicate function.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new `LinkedHashMap` containing key-value pairs from the original
|
||||
* map that satisfy a given predicate function.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes four arguments:
|
||||
* `value`, `key`, `index`, and `this`. It should return a boolean value indicating whether the
|
||||
* current element should be included in the filtered map or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the `predicate` function. It is used when you want to bind a
|
||||
* specific object as the context for the `predicate` function. If `thisArg` is not provided, `this
|
||||
* @returns a new `LinkedHashMap` object that contains the key-value pairs from the original
|
||||
* `LinkedHashMap` object that satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: (element: [K, V], index: number, map: LinkedHashMap<K, V>) => boolean): LinkedHashMap<K, V> {
|
||||
filter(predicate: PairCallback<K, V, boolean>, thisArg?: any): LinkedHashMap<K, V> {
|
||||
const filteredMap = new LinkedHashMap<K, V>();
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
if (predicate([key, value], index, this)) {
|
||||
if (predicate.call(thisArg, value, key, index, this)) {
|
||||
filteredMap.set(key, value);
|
||||
}
|
||||
index++;
|
||||
|
@ -682,43 +580,40 @@ export class LinkedHashMap<K = any, V = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The `map` function takes a callback function and returns a new LinkedHashMap with the values transformed
|
||||
* by the callback.
|
||||
* @param callback - The `callback` parameter is a function that takes two arguments: `element` and
|
||||
* `map`.
|
||||
* @returns a new LinkedHashMap object with the values mapped according to the provided callback function.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
map<NV>(callback: (element: [K, V], index: number, map: LinkedHashMap<K, V>) => NV): LinkedHashMap<K, NV> {
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function in TypeScript creates a new `LinkedHashMap` by applying a callback function to
|
||||
* each key-value pair in the original map.
|
||||
* @param callback - The callback parameter is a function that will be called for each key-value pair
|
||||
* in the map. It takes four arguments: the value of the current key-value pair, the key of the
|
||||
* current key-value pair, the index of the current key-value pair, and the map itself. The callback
|
||||
* function should
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the callback function. If provided, the callback function will
|
||||
* be called with `thisArg` as its `this` value. If not provided, `this` will refer to the current
|
||||
* map
|
||||
* @returns a new `LinkedHashMap` object with the values mapped according to the provided callback
|
||||
* function.
|
||||
*/
|
||||
map<NV>(callback: PairCallback<K, V, NV>, thisArg?: any): LinkedHashMap<K, NV> {
|
||||
const mappedMap = new LinkedHashMap<K, NV>();
|
||||
let index = 0;
|
||||
for (const [key, value] of this) {
|
||||
const newValue = callback([key, value], index, this);
|
||||
const newValue = callback.call(thisArg, value, key, index, this);
|
||||
mappedMap.set(key, newValue);
|
||||
index++;
|
||||
}
|
||||
return mappedMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `reduce` function iterates over the elements of a LinkedHashMap and applies a callback function to
|
||||
* each element, accumulating a single value.
|
||||
* @param callback - The callback parameter is a function that takes three arguments: accumulator,
|
||||
* element, and map. It is called for each element in the LinkedHashMap and is used to accumulate a single
|
||||
* result.
|
||||
* @param {A} initialValue - The `initialValue` parameter is the initial value of the accumulator. It
|
||||
* is the value that will be passed as the first argument to the `callback` function when reducing
|
||||
* the elements of the map.
|
||||
* @returns The `reduce` function is returning the final value of the accumulator after iterating
|
||||
* over all the elements in the LinkedHashMap and applying the callback function to each element.
|
||||
*/
|
||||
reduce<A>(callback: (accumulator: A, element: [K, V], index: number, map: LinkedHashMap<K, V>) => A, initialValue: A): A {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const entry of this) {
|
||||
accumulator = callback(accumulator, entry, index, this);
|
||||
index++;
|
||||
}
|
||||
return accumulator;
|
||||
print() {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -727,7 +622,7 @@ export class LinkedHashMap<K = any, V = any> {
|
|||
*
|
||||
* The above function is an iterator that yields key-value pairs from a linked list.
|
||||
*/
|
||||
* [Symbol.iterator]() {
|
||||
protected* _getIterator() {
|
||||
let node = this._head;
|
||||
while (node !== this._sentinel) {
|
||||
yield <[K, V]>[node.key, node.value];
|
||||
|
@ -735,10 +630,6 @@ export class LinkedHashMap<K = any, V = any> {
|
|||
}
|
||||
}
|
||||
|
||||
print() {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(1)
|
||||
* Space Complexity: O(1)
|
||||
|
|
|
@ -5,13 +5,15 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import type { Comparator, DFSOrderPattern } from '../../types';
|
||||
import type { Comparator, DFSOrderPattern, ElementCallback } from '../../types';
|
||||
import { HeapOptions } from "../../types";
|
||||
import { IterableElementBase } from "../base";
|
||||
|
||||
export class Heap<E = any> {
|
||||
export class Heap<E = any> extends IterableElementBase<E> {
|
||||
options: HeapOptions<E>;
|
||||
|
||||
constructor(elements?: Iterable<E>, options?: HeapOptions<E>) {
|
||||
super();
|
||||
const defaultComparator = (a: E, b: E) => {
|
||||
if (!(typeof a === 'number' && typeof b === 'number')) {
|
||||
throw new Error('The a, b params of compare function must be number');
|
||||
|
@ -339,56 +341,75 @@ export class Heap<E = any> {
|
|||
for (let i = Math.floor(this.size / 2); i >= 0; i--) this._sinkDown(i, this.elements.length >> 1);
|
||||
}
|
||||
|
||||
* [Symbol.iterator]() {
|
||||
for (const element of this.elements) {
|
||||
yield element;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
forEach(callback: (element: E, index: number, heap: this) => void): void {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new Heap object containing elements that pass a given callback
|
||||
* function.
|
||||
* @param callback - The `callback` parameter is a function that will be called for each element in
|
||||
* the heap. It takes three arguments: the current element, the index of the current element, and the
|
||||
* heap itself. The callback function should return a boolean value indicating whether the current
|
||||
* element should be included in the filtered list
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new `Heap` object that contains the elements that pass
|
||||
* the filter condition specified by the `callback` function.
|
||||
*/
|
||||
filter(callback: ElementCallback<E, boolean>, thisArg?: any): Heap<E> {
|
||||
const filteredList = new Heap<E>();
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
callback(el, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
filter(predicate: (element: E, index: number, heap: Heap<E>) => boolean): Heap<E> {
|
||||
const filteredHeap: Heap<E> = new Heap<E>([], this.options);
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
if (predicate(el, index, this)) {
|
||||
filteredHeap.push(el);
|
||||
for (const current of this) {
|
||||
if (callback.call(thisArg, current, index, this)) {
|
||||
filteredList.push(current);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return filteredHeap;
|
||||
return filteredList;
|
||||
}
|
||||
|
||||
map<T>(callback: (element: E, index: number, heap: Heap<E>) => T, comparator: Comparator<T>): Heap<T> {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function creates a new heap by applying a callback function to each element of the
|
||||
* original heap.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* original heap. It takes three arguments: the current element, the index of the current element,
|
||||
* and the original heap itself. The callback function should return a value of type T, which will be
|
||||
* added to the mapped heap.
|
||||
* @param comparator - The `comparator` parameter is a function that is used to compare elements in
|
||||
* the heap. It takes two arguments, `a` and `b`, and returns a negative number if `a` is less than
|
||||
* `b`, a positive number if `a` is greater than `b`, or
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the callback function. It is used when you want to bind a
|
||||
* specific object as the context for the callback function. If `thisArg` is not provided,
|
||||
* `undefined` is used as
|
||||
* @returns a new instance of the Heap class, which is created using the mapped elements from the
|
||||
* original Heap.
|
||||
*/
|
||||
map<T>(callback: ElementCallback<E, T>, comparator: Comparator<T>, thisArg?: any): Heap<T> {
|
||||
|
||||
const mappedHeap: Heap<T> = new Heap<T>([], { comparator: comparator });
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
mappedHeap.add(callback(el, index, this));
|
||||
mappedHeap.add(callback.call(thisArg, el, index, this));
|
||||
index++;
|
||||
}
|
||||
return mappedHeap;
|
||||
}
|
||||
|
||||
reduce<T>(
|
||||
callback: (accumulator: T, currentValue: E, currentIndex: number, heap: Heap<E>) => T,
|
||||
initialValue: T
|
||||
): T {
|
||||
let accumulator: T = initialValue;
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
accumulator = callback(accumulator, el, index, this);
|
||||
index++;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(log n)
|
||||
* Space Complexity: O(1)
|
||||
|
@ -398,6 +419,12 @@ export class Heap<E = any> {
|
|||
console.log([...this]);
|
||||
}
|
||||
|
||||
protected* _getIterator() {
|
||||
for (const element of this.elements) {
|
||||
yield element;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
|
|
|
@ -9,3 +9,4 @@ export * from './heap';
|
|||
export * from './priority-queue';
|
||||
export * from './matrix';
|
||||
export * from './trie';
|
||||
export * from './base';
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { IterableElementBase } from "../base";
|
||||
import { ElementCallback } from "../../types";
|
||||
|
||||
/**
|
||||
* data-structure-typed
|
||||
*
|
||||
|
@ -22,11 +25,12 @@ export class DoublyLinkedListNode<E = any> {
|
|||
}
|
||||
}
|
||||
|
||||
export class DoublyLinkedList<E = any> {
|
||||
export class DoublyLinkedList<E = any> extends IterableElementBase<E> {
|
||||
/**
|
||||
* The constructor initializes the linked list with an empty head, tail, and length.
|
||||
*/
|
||||
constructor(elements?: Iterable<E>) {
|
||||
super();
|
||||
this._head = undefined;
|
||||
this._tail = undefined;
|
||||
this._length = 0;
|
||||
|
@ -724,59 +728,32 @@ export class DoublyLinkedList<E = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that iterates over the values of a linked list.
|
||||
*/
|
||||
* [Symbol.iterator]() {
|
||||
let current = this.head;
|
||||
|
||||
while (current) {
|
||||
yield current.value;
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each element in a linked list and applies a callback function to each element.
|
||||
* @param callback - The callback parameter is a function that takes two arguments: value and index. The value argument
|
||||
* represents the value of the current node in the linked list, and the index argument represents the index of the
|
||||
* current node in the linked list.
|
||||
*/
|
||||
forEach(callback: (value: E, index: number, list: DoublyLinkedList<E>) => void): void {
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
callback(el, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function iterates through a DoublyLinkedList and returns a new DoublyLinkedList containing only the
|
||||
* elements that satisfy the given callback function.
|
||||
* @param callback - The `callback` parameter is a function that takes a value of type `E` and returns a boolean value.
|
||||
* It is used to determine whether a value should be included in the filtered list or not.
|
||||
* @returns The filtered list, which is an instance of the DoublyLinkedList class.
|
||||
* The `filter` function creates a new DoublyLinkedList by iterating over the elements of the current
|
||||
* list and applying a callback function to each element, returning only the elements for which the
|
||||
* callback function returns true.
|
||||
* @param callback - The `callback` parameter is a function that will be called for each element in
|
||||
* the DoublyLinkedList. It takes three arguments: the current element, the index of the current
|
||||
* element, and the DoublyLinkedList itself. The callback function should return a boolean value
|
||||
* indicating whether the current element should be included
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new `DoublyLinkedList` object that contains the
|
||||
* elements that pass the filter condition specified by the `callback` function.
|
||||
*/
|
||||
filter(callback: (value: E, index: number, list: DoublyLinkedList<E>) => boolean): DoublyLinkedList<E> {
|
||||
filter(callback: ElementCallback<E, boolean>, thisArg?: any): DoublyLinkedList<E> {
|
||||
const filteredList = new DoublyLinkedList<E>();
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
if (callback(current, index, this)) {
|
||||
if (callback.call(thisArg, current, index, this)) {
|
||||
filteredList.push(current);
|
||||
}
|
||||
index++;
|
||||
|
@ -790,21 +767,27 @@ export class DoublyLinkedList<E = any> {
|
|||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function takes a callback function and applies it to each element in the DoublyLinkedList, returning a new
|
||||
* DoublyLinkedList with the transformed values.
|
||||
* @param callback - The callback parameter is a function that takes a value of type E (the type of values stored in
|
||||
* the original DoublyLinkedList) and returns a value of type T (the type of values that will be stored in the mapped
|
||||
* DoublyLinkedList).
|
||||
* @returns The `map` function is returning a new instance of `DoublyLinkedList<T>` that contains the mapped values.
|
||||
* The `map` function creates a new DoublyLinkedList by applying a callback function to each element
|
||||
* in the original list.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* DoublyLinkedList. It takes three arguments: the current element, the index of the current element,
|
||||
* and the DoublyLinkedList itself. The callback function should return a value that will be added to
|
||||
* the new DoublyLinkedList that
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `map` function is returning a new `DoublyLinkedList` object that contains the results
|
||||
* of applying the provided `callback` function to each element in the original `DoublyLinkedList`
|
||||
* object.
|
||||
*/
|
||||
map<T>(callback: (value: E, index: number, list: DoublyLinkedList<E>) => T): DoublyLinkedList<T> {
|
||||
map<T>(callback: ElementCallback<E, T>, thisArg?: any): DoublyLinkedList<T> {
|
||||
const mappedList = new DoublyLinkedList<T>();
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
mappedList.push(callback(current, index, this));
|
||||
mappedList.push(callback.call(thisArg, current, index, this));
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -816,31 +799,19 @@ export class DoublyLinkedList<E = any> {
|
|||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `reduce` function iterates over a linked list and applies a callback function to each element, accumulating a
|
||||
* single value.
|
||||
* @param callback - The `callback` parameter is a function that takes two arguments: `accumulator` and `value`. It is
|
||||
* used to perform a specific operation on each element of the linked list.
|
||||
* @param {T} initialValue - The `initialValue` parameter is the initial value of the accumulator. It is the starting
|
||||
* point for the reduction operation.
|
||||
* @returns The `reduce` method is returning the final value of the accumulator after iterating through all the
|
||||
* elements in the linked list.
|
||||
*/
|
||||
reduce<T>(callback: (accumulator: T, value: E, index: number, list: DoublyLinkedList<E>) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
accumulator = callback(accumulator, current, index, this);
|
||||
index++;
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
print(): void {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that iterates over the values of a linked list.
|
||||
*/
|
||||
protected* _getIterator(): IterableIterator<E> {
|
||||
let current = this.head;
|
||||
|
||||
while (current) {
|
||||
yield current.value;
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
import { IterableElementBase } from "../base";
|
||||
import { ElementCallback } from "../../types";
|
||||
|
||||
/**
|
||||
* data-structure-typed
|
||||
*
|
||||
|
@ -20,11 +23,12 @@ export class SinglyLinkedListNode<E = any> {
|
|||
}
|
||||
}
|
||||
|
||||
export class SinglyLinkedList<E = any> {
|
||||
export class SinglyLinkedList<E = any> extends IterableElementBase<E> {
|
||||
/**
|
||||
* The constructor initializes the linked list with an empty head, tail, and length.
|
||||
*/
|
||||
constructor(elements?: Iterable<E>) {
|
||||
super();
|
||||
this._head = undefined;
|
||||
this._tail = undefined;
|
||||
this._length = 0;
|
||||
|
@ -670,59 +674,32 @@ export class SinglyLinkedList<E = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* The function returns an iterator that iterates over the values of a linked list.
|
||||
*/
|
||||
* [Symbol.iterator]() {
|
||||
let current = this.head;
|
||||
|
||||
while (current) {
|
||||
yield current.value;
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each element in a linked list and applies a callback function to each element.
|
||||
* @param callback - The callback parameter is a function that takes two arguments: value and index. The value argument
|
||||
* represents the value of the current node in the linked list, and the index argument represents the index of the
|
||||
* current node in the linked list.
|
||||
*/
|
||||
forEach(callback: (value: E, index: number, list: SinglyLinkedList<E>) => void): void {
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
callback(el, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function iterates through a SinglyLinkedList and returns a new SinglyLinkedList containing only the
|
||||
* elements that satisfy the given callback function.
|
||||
* @param callback - The `callback` parameter is a function that takes a value of type `E` and returns a boolean value.
|
||||
* It is used to determine whether a value should be included in the filtered list or not.
|
||||
* @returns The filtered list, which is an instance of the SinglyLinkedList class.
|
||||
* The `filter` function creates a new SinglyLinkedList by iterating over the elements of the current
|
||||
* list and applying a callback function to each element to determine if it should be included in the
|
||||
* filtered list.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* list. It takes three arguments: the current element, the index of the current element, and the
|
||||
* list itself. The callback function should return a boolean value indicating whether the current
|
||||
* element should be included in the filtered list or not
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new `SinglyLinkedList` object that contains the
|
||||
* elements that pass the filter condition specified by the `callback` function.
|
||||
*/
|
||||
filter(callback: (value: E, index: number, list: SinglyLinkedList<E>) => boolean): SinglyLinkedList<E> {
|
||||
filter(callback: ElementCallback<E, boolean>, thisArg?: any): SinglyLinkedList<E> {
|
||||
const filteredList = new SinglyLinkedList<E>();
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
if (callback(current, index, this)) {
|
||||
if (callback.call(thisArg, current, index, this)) {
|
||||
filteredList.push(current);
|
||||
}
|
||||
index++;
|
||||
|
@ -730,27 +707,30 @@ export class SinglyLinkedList<E = any> {
|
|||
return filteredList;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function takes a callback function and applies it to each element in the SinglyLinkedList, returning a new
|
||||
* SinglyLinkedList with the transformed values.
|
||||
* @param callback - The callback parameter is a function that takes a value of type E (the type of values stored in
|
||||
* the original SinglyLinkedList) and returns a value of type T (the type of values that will be stored in the mapped
|
||||
* SinglyLinkedList).
|
||||
* @returns The `map` function is returning a new instance of `SinglyLinkedList<T>` that contains the mapped values.
|
||||
*/
|
||||
map<T>(callback: (value: E, index: number, list: SinglyLinkedList<E>) => T): SinglyLinkedList<T> {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function creates a new SinglyLinkedList by applying a callback function to each element
|
||||
* of the original list.
|
||||
* @param callback - The `callback` parameter is a function that will be called for each element in
|
||||
* the linked list. It takes three arguments:
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `map` function is returning a new `SinglyLinkedList` object that contains the results
|
||||
* of applying the provided `callback` function to each element in the original list.
|
||||
*/
|
||||
map<T>(callback: ElementCallback<E, T>, thisArg?: any): SinglyLinkedList<T> {
|
||||
const mappedList = new SinglyLinkedList<T>();
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
mappedList.push(callback(current, index, this));
|
||||
mappedList.push(callback.call(thisArg, current, index, this));
|
||||
index++;
|
||||
}
|
||||
|
||||
|
@ -762,31 +742,16 @@ export class SinglyLinkedList<E = any> {
|
|||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n), where n is the number of elements in the linked list.
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `reduce` function iterates over a linked list and applies a callback function to each element, accumulating a
|
||||
* single value.
|
||||
* @param callback - The `callback` parameter is a function that takes two arguments: `accumulator` and `value`. It is
|
||||
* used to perform a specific operation on each element of the linked list.
|
||||
* @param {T} initialValue - The `initialValue` parameter is the initial value of the accumulator. It is the starting
|
||||
* point for the reduction operation.
|
||||
* @returns The `reduce` method is returning the final value of the accumulator after iterating through all the
|
||||
* elements in the linked list.
|
||||
*/
|
||||
reduce<T>(callback: (accumulator: T, value: E, index: number, list: SinglyLinkedList<E>) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const current of this) {
|
||||
accumulator = callback(accumulator, current, index, this);
|
||||
index++;
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
print(): void {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
protected* _getIterator(): IterableIterator<E> {
|
||||
let current = this.head;
|
||||
|
||||
while (current) {
|
||||
yield current.value;
|
||||
current = current.next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
*/
|
||||
|
||||
|
||||
import { IterableWithSizeOrLength } from "../../types";
|
||||
import { ElementCallback, IterableWithSizeOrLength } from "../../types";
|
||||
import { calcMinUnitsRequired, rangeCheck } from "../../utils";
|
||||
import { IterableElementBase } from "../base";
|
||||
|
||||
/**
|
||||
* Deque can provide random access with O(1) time complexity
|
||||
|
@ -17,7 +18,7 @@ import { calcMinUnitsRequired, rangeCheck } from "../../utils";
|
|||
* Deque is implemented using a dynamic array. Inserting or deleting beyond both ends of the array may require moving elements or reallocating space.
|
||||
*/
|
||||
|
||||
export class Deque<E> {
|
||||
export class Deque<E> extends IterableElementBase<E> {
|
||||
protected _bucketFirst = 0;
|
||||
protected _firstInBucket = 0;
|
||||
protected _bucketLast = 0;
|
||||
|
@ -35,7 +36,7 @@ export class Deque<E> {
|
|||
* stored in each bucket. It determines the size of each bucket in the data structure.
|
||||
*/
|
||||
constructor(elements: IterableWithSizeOrLength<E> = [], bucketSize = (1 << 12)) {
|
||||
|
||||
super();
|
||||
let _size: number;
|
||||
if ('length' in elements) {
|
||||
if (elements.length instanceof Function) _size = elements.length(); else _size = elements.length;
|
||||
|
@ -699,67 +700,31 @@ export class Deque<E> {
|
|||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The above function is an implementation of the iterator protocol in TypeScript, allowing the
|
||||
* object to be iterated over using a for...of loop.
|
||||
*/
|
||||
* [Symbol.iterator]() {
|
||||
for (let i = 0; i < this.size; ++i) {
|
||||
yield this.getAt(i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each element in a deque and applies a callback function to
|
||||
* each element.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* deque. It takes three parameters:
|
||||
*/
|
||||
forEach(callback: (element: E, index: number, deque: this) => void) {
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
callback(el, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new deque containing only the elements that satisfy the given
|
||||
* predicate function.
|
||||
* @param predicate - The `predicate` parameter is a function that takes three arguments: `element`,
|
||||
* `index`, and `deque`.
|
||||
* @returns The `filter` method is returning a new `Deque` object that contains only the elements
|
||||
* that satisfy the given `predicate` function.
|
||||
* The `filter` function creates a new deque containing elements from the original deque that satisfy
|
||||
* a given predicate function.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* the current element being iterated over, the index of the current element, and the deque itself.
|
||||
* It should return a boolean value indicating whether the element should be included in the filtered
|
||||
* deque or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new `Deque` object that contains the elements that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: (element: E, index: number, deque: this) => boolean): Deque<E> {
|
||||
filter(predicate: ElementCallback<E, boolean>, thisArg?: any): Deque<E> {
|
||||
const newDeque = new Deque<E>([], this._bucketSize);
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
if (predicate(el, index, this)) {
|
||||
if (predicate.call(thisArg, el, index, this)) {
|
||||
newDeque.push(el);
|
||||
}
|
||||
index++;
|
||||
|
@ -771,21 +736,24 @@ export class Deque<E> {
|
|||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function takes a callback function and applies it to each element in the deque,
|
||||
* returning a new deque with the results.
|
||||
* @param callback - The `callback` parameter is a function that takes three arguments:
|
||||
* @returns The `map` method is returning a new `Deque` object with the transformed elements.
|
||||
* The `map` function creates a new Deque by applying a callback function to each element of the
|
||||
* original Deque.
|
||||
* @param callback - The `callback` parameter is a function that will be called for each element in
|
||||
* the deque. It takes three arguments:
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns a new Deque object with the mapped values.
|
||||
*/
|
||||
map<T>(callback: (element: E, index: number, deque: this) => T): Deque<T> {
|
||||
map<T>(callback: ElementCallback<E, T>, thisArg?: any): Deque<T> {
|
||||
const newDeque = new Deque<T>([], this._bucketSize);
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
newDeque.push(callback(el, index, this));
|
||||
newDeque.push(callback.call(thisArg, el, index, this));
|
||||
index++;
|
||||
}
|
||||
return newDeque;
|
||||
|
@ -793,34 +761,24 @@ export class Deque<E> {
|
|||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
print(): void {
|
||||
console.log([...this])
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `reduce` function iterates over the elements of a deque and applies a callback function to
|
||||
* each element, accumulating a single value.
|
||||
* @param callback - The `callback` parameter is a function that takes four arguments:
|
||||
* @param {T} initialValue - The `initialValue` parameter is the initial value of the accumulator. It
|
||||
* is the value that will be passed as the first argument to the `callback` function when reducing
|
||||
* the elements of the deque.
|
||||
* @returns the final value of the accumulator after iterating over all elements in the deque and
|
||||
* applying the callback function to each element.
|
||||
* The above function is an implementation of the iterator protocol in TypeScript, allowing the
|
||||
* object to be iterated over using a for...of loop.
|
||||
*/
|
||||
reduce<T>(callback: (accumulator: T, element: E, index: number, deque: this) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
accumulator = callback(accumulator, el, index, this);
|
||||
index++;
|
||||
protected* _getIterator() {
|
||||
for (let i = 0; i < this.size; ++i) {
|
||||
yield this.getAt(i);
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
print(): void {
|
||||
console.log([...this])
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -4,42 +4,10 @@
|
|||
* @class
|
||||
*/
|
||||
import { SinglyLinkedList } from '../linked-list';
|
||||
import { IterableElementBase } from "../base";
|
||||
import { ElementCallback } from "../../types";
|
||||
|
||||
export class LinkedListQueue<E = any> extends SinglyLinkedList<E> {
|
||||
/**
|
||||
* The enqueue function adds a value to the end of an array.
|
||||
* @param {E} value - The value parameter represents the value that you want to add to the queue.
|
||||
*/
|
||||
enqueue(value: E) {
|
||||
this.push(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The `dequeue` function removes and returns the first element from a queue, or returns undefined if the queue is empty.
|
||||
* @returns The method is returning the element at the front of the queue, or undefined if the queue is empty.
|
||||
*/
|
||||
dequeue(): E | undefined {
|
||||
return this.shift();
|
||||
}
|
||||
|
||||
/**
|
||||
* The `getFirst` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
|
||||
* @returns The `getFirst()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
|
||||
*/
|
||||
getFirst(): E | undefined {
|
||||
return this.head?.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
|
||||
* @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
|
||||
*/
|
||||
peek(): E | undefined {
|
||||
return this.getFirst();
|
||||
}
|
||||
}
|
||||
|
||||
export class Queue<E = any> {
|
||||
export class Queue<E = any> extends IterableElementBase<E> {
|
||||
/**
|
||||
* The constructor initializes an instance of a class with an optional array of elements and sets the offset to 0.
|
||||
* @param {E[]} [elements] - The `elements` parameter is an optional array of elements of type `E`. If provided, it
|
||||
|
@ -47,6 +15,7 @@ export class Queue<E = any> {
|
|||
* initialized as an empty array.
|
||||
*/
|
||||
constructor(elements?: E[]) {
|
||||
super();
|
||||
this._nodes = elements || [];
|
||||
this._offset = 0;
|
||||
}
|
||||
|
@ -304,34 +273,6 @@ export class Queue<E = any> {
|
|||
console.log([...this]);
|
||||
}
|
||||
|
||||
* [Symbol.iterator]() {
|
||||
for (const item of this.nodes) {
|
||||
yield item;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(1)
|
||||
*
|
||||
* The `forEach` function iterates over each element in a deque and applies a callback function to
|
||||
* each element.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* deque. It takes three parameters:
|
||||
*/
|
||||
forEach(callback: (element: E, index: number, queue: this) => void) {
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
callback(el, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
|
@ -341,18 +282,23 @@ export class Queue<E = any> {
|
|||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new deque containing only the elements that satisfy the given
|
||||
* predicate function.
|
||||
* @param predicate - The `predicate` parameter is a function that takes three arguments: `element`,
|
||||
* `index`, and `deque`.
|
||||
* @returns The `filter` method is returning a new `Queue` object that contains only the elements
|
||||
* that satisfy the given `predicate` function.
|
||||
* The `filter` function creates a new `Queue` object containing elements from the original `Queue`
|
||||
* that satisfy a given predicate function.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* the current element being iterated over, the index of the current element, and the queue itself.
|
||||
* It should return a boolean value indicating whether the element should be included in the filtered
|
||||
* queue or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new `Queue` object that contains the elements that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
filter(predicate: (element: E, index: number, queue: this) => boolean): Queue<E> {
|
||||
filter(predicate: ElementCallback<E, boolean>, thisArg?: any): Queue<E> {
|
||||
const newDeque = new Queue<E>([]);
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
if (predicate(el, index, this)) {
|
||||
if (predicate.call(thisArg, el, index, this)) {
|
||||
newDeque.push(el);
|
||||
}
|
||||
index++;
|
||||
|
@ -364,33 +310,72 @@ export class Queue<E = any> {
|
|||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function takes a callback function and applies it to each element in the deque,
|
||||
* returning a new deque with the results.
|
||||
* @param callback - The `callback` parameter is a function that takes three arguments:
|
||||
* @returns The `map` method is returning a new `Queue` object with the transformed elements.
|
||||
* The `map` function takes a callback function and applies it to each element in the queue,
|
||||
* returning a new queue with the results.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* queue. It takes three arguments: the current element, the index of the current element, and the
|
||||
* queue itself. The callback function should return a new value that will be added to the new queue.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `map` function is returning a new `Queue` object with the transformed elements.
|
||||
*/
|
||||
map<T>(callback: (element: E, index: number, queue: this) => T): Queue<T> {
|
||||
map<T>(callback: ElementCallback<E, T>, thisArg?: any): Queue<T> {
|
||||
const newDeque = new Queue<T>([]);
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
newDeque.push(callback(el, index, this));
|
||||
newDeque.push(callback.call(thisArg, el, index, this));
|
||||
index++;
|
||||
}
|
||||
return newDeque;
|
||||
}
|
||||
|
||||
reduce<T>(callback: (accumulator: T, element: E, index: number, queue: this) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
accumulator = callback(accumulator, el, index, this);
|
||||
index++;
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
protected* _getIterator() {
|
||||
for (const item of this.nodes) {
|
||||
yield item;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
}
|
||||
|
||||
export class LinkedListQueue<E = any> extends SinglyLinkedList<E> {
|
||||
/**
|
||||
* The enqueue function adds a value to the end of an array.
|
||||
* @param {E} value - The value parameter represents the value that you want to add to the queue.
|
||||
*/
|
||||
enqueue(value: E) {
|
||||
this.push(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* The `dequeue` function removes and returns the first element from a queue, or returns undefined if the queue is empty.
|
||||
* @returns The method is returning the element at the front of the queue, or undefined if the queue is empty.
|
||||
*/
|
||||
dequeue(): E | undefined {
|
||||
return this.shift();
|
||||
}
|
||||
|
||||
/**
|
||||
* The `getFirst` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
|
||||
* @returns The `getFirst()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
|
||||
*/
|
||||
getFirst(): E | undefined {
|
||||
return this.head?.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `peek` function returns the value of the head node in a linked list, or `undefined` if the list is empty.
|
||||
* @returns The `peek()` method is returning the value of the `head` node if it exists, otherwise it returns `undefined`.
|
||||
*/
|
||||
peek(): E | undefined {
|
||||
return this.getFirst();
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
import { IterableElementBase } from "../base";
|
||||
import { ElementCallback } from "../../types";
|
||||
|
||||
/**
|
||||
* @license MIT
|
||||
* @copyright Tyler Zeng <zrwusa@gmail.com>
|
||||
* @class
|
||||
*/
|
||||
export class Stack<E = any> {
|
||||
export class Stack<E = any> extends IterableElementBase<E> {
|
||||
/**
|
||||
* The constructor initializes an array of elements, which can be provided as an optional parameter.
|
||||
* @param {E[]} [elements] - The `elements` parameter is an optional parameter of type `E[]`, which represents an array
|
||||
|
@ -11,6 +14,7 @@ export class Stack<E = any> {
|
|||
* is provided and is an array, it is assigned to the `_elements
|
||||
*/
|
||||
constructor(elements?: Iterable<E>) {
|
||||
super();
|
||||
this._elements = [];
|
||||
if (elements) {
|
||||
for (const el of elements) {
|
||||
|
@ -154,33 +158,31 @@ export class Stack<E = any> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Custom iterator for the Stack class.
|
||||
* @returns An iterator object.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
* [Symbol.iterator]() {
|
||||
for (let i = 0; i < this.elements.length; i++) {
|
||||
yield this.elements[i];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a function to each element of the stack.
|
||||
* @param {function(E): void} callback - A function to apply to each element.
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function creates a new stack containing elements from the original stack that satisfy
|
||||
* a given predicate function.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* the current element being iterated over, the index of the current element, and the stack itself.
|
||||
* It should return a boolean value indicating whether the element should be included in the filtered
|
||||
* stack or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `predicate` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `predicate` function. If `thisArg` is
|
||||
* @returns The `filter` method is returning a new `Stack` object that contains the elements that
|
||||
* satisfy the given predicate function.
|
||||
*/
|
||||
forEach(callback: (element: E, index: number, stack: this) => void): void {
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
callback(el, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
filter(predicate: (element: E, index: number, stack: this) => boolean): Stack<E> {
|
||||
filter(predicate: ElementCallback<E, boolean>, thisArg?: any): Stack<E> {
|
||||
const newStack = new Stack<E>();
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
if (predicate(el, index, this)) {
|
||||
if (predicate.call(thisArg, el, index, this)) {
|
||||
newStack.push(el);
|
||||
}
|
||||
index++;
|
||||
|
@ -188,28 +190,45 @@ export class Stack<E = any> {
|
|||
return newStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
map<T>(callback: (element: E, index: number, stack: this) => T): Stack<T> {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function takes a callback function and applies it to each element in the stack,
|
||||
* returning a new stack with the results.
|
||||
* @param callback - The `callback` parameter is a function that will be called for each element in
|
||||
* the stack. It takes three arguments:
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `map` method is returning a new `Stack` object.
|
||||
*/
|
||||
map<T>(callback: ElementCallback<E, T>, thisArg?: any): Stack<T> {
|
||||
const newStack = new Stack<T>();
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
newStack.push(callback(el, index, this));
|
||||
newStack.push(callback.call(thisArg, el, index, this));
|
||||
index++;
|
||||
}
|
||||
return newStack;
|
||||
}
|
||||
|
||||
reduce<T>(callback: (accumulator: T, element: E, index: number, stack: this) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const el of this) {
|
||||
accumulator = callback(accumulator, el, index, this);
|
||||
index++;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
print(): void {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom iterator for the Stack class.
|
||||
* @returns An iterator object.
|
||||
*/
|
||||
protected* _getIterator() {
|
||||
for (let i = 0; i < this.elements.length; i++) {
|
||||
yield this.elements[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
* @license MIT License
|
||||
*/
|
||||
|
||||
import { IterableElementBase } from "../base";
|
||||
import { ElementCallback } from "../../types";
|
||||
|
||||
/**
|
||||
* TrieNode represents a node in the Trie data structure. It holds a character key, a map of children nodes,
|
||||
* and a flag indicating whether it's the end of a word.
|
||||
|
@ -25,8 +28,9 @@ export class TrieNode {
|
|||
/**
|
||||
* Trie represents a Trie data structure. It provides basic Trie operations and additional methods.
|
||||
*/
|
||||
export class Trie {
|
||||
export class Trie extends IterableElementBase<string> {
|
||||
constructor(words?: string[], caseSensitive = true) {
|
||||
super();
|
||||
this._root = new TrieNode('');
|
||||
this._caseSensitive = caseSensitive;
|
||||
this._size = 0;
|
||||
|
@ -339,7 +343,70 @@ export class Trie {
|
|||
return words;
|
||||
}
|
||||
|
||||
* [Symbol.iterator](): IterableIterator<string> {
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `filter` function takes a predicate function and returns a new array containing all the
|
||||
* elements for which the predicate function returns true.
|
||||
* @param predicate - The `predicate` parameter is a callback function that takes three arguments:
|
||||
* `word`, `index`, and `this`. It should return a boolean value indicating whether the current
|
||||
* element should be included in the filtered results or not.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that allows you to
|
||||
* specify the value of `this` within the `predicate` function. It is used when you want to bind a
|
||||
* specific object as the context for the `predicate` function. If `thisArg` is provided, it will be
|
||||
* @returns The `filter` method is returning an array of strings (`string[]`).
|
||||
*/
|
||||
filter(predicate: ElementCallback<string, boolean>, thisArg?: any): string[] {
|
||||
const results: string[] = [];
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
if (predicate.call(thisArg, word, index, this)) {
|
||||
results.push(word);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Time Complexity: O(n)
|
||||
* Space Complexity: O(n)
|
||||
*
|
||||
* The `map` function creates a new Trie by applying a callback function to each element in the Trie.
|
||||
* @param callback - The callback parameter is a function that will be called for each element in the
|
||||
* Trie. It takes three arguments: the current element in the Trie, the index of the current element,
|
||||
* and the Trie itself. The callback function should return a new value for the element.
|
||||
* @param {any} [thisArg] - The `thisArg` parameter is an optional argument that specifies the value
|
||||
* to be used as `this` when executing the `callback` function. If `thisArg` is provided, it will be
|
||||
* passed as the `this` value to the `callback` function. If `thisArg` is
|
||||
* @returns The `map` function is returning a new Trie object.
|
||||
*/
|
||||
map(callback: ElementCallback<string, string>, thisArg?: any): Trie {
|
||||
const newTrie = new Trie();
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
newTrie.add(callback.call(thisArg, word, index, this));
|
||||
index++;
|
||||
}
|
||||
return newTrie;
|
||||
}
|
||||
|
||||
print() {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
protected* _getIterator(): IterableIterator<string> {
|
||||
function* _dfs(node: TrieNode, path: string): IterableIterator<string> {
|
||||
if (node.isEnd) {
|
||||
yield path;
|
||||
|
@ -352,50 +419,6 @@ export class Trie {
|
|||
yield* _dfs(this.root, '');
|
||||
}
|
||||
|
||||
forEach(callback: (word: string, index: number, trie: this) => void): void {
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
callback(word, index, this);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
filter(predicate: (word: string, index: number, trie: this) => boolean): string[] {
|
||||
const results: string[] = [];
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
if (predicate(word, index, this)) {
|
||||
results.push(word);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
map(callback: (word: string, index: number, trie: this) => string): Trie {
|
||||
const newTrie = new Trie();
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
newTrie.add(callback(word, index, this));
|
||||
index++;
|
||||
}
|
||||
return newTrie;
|
||||
}
|
||||
|
||||
reduce<T>(callback: (accumulator: T, word: string, index: number, trie: this) => T, initialValue: T): T {
|
||||
let accumulator = initialValue;
|
||||
let index = 0;
|
||||
for (const word of this) {
|
||||
accumulator = callback(accumulator, word, index, this);
|
||||
index++;
|
||||
}
|
||||
return accumulator;
|
||||
}
|
||||
|
||||
print() {
|
||||
console.log([...this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time Complexity: O(M), where M is the length of the input string.
|
||||
* Space Complexity: O(1) - Constant space.
|
||||
|
|
6
src/types/data-structures/base/base.ts
Normal file
6
src/types/data-structures/base/base.ts
Normal file
|
@ -0,0 +1,6 @@
|
|||
import { IterableElementBase, IterablePairBase } from "../../../data-structures";
|
||||
|
||||
export type PairCallback<K, V, R> = (value: V, key: K, index: number, container: IterablePairBase<K, V>) => R;
|
||||
export type ElementCallback<V, R> = (element: V, index: number, container: IterableElementBase<V>) => R;
|
||||
export type ReducePairCallback<K, V, R> = (accumulator: R, value: V, key: K, index: number, container: IterablePairBase<K, V>) => R;
|
||||
export type ReduceElementCallback<V, R> = (accumulator: R, element: V, index: number, container: IterableElementBase<V>) => R;
|
1
src/types/data-structures/base/index.ts
Normal file
1
src/types/data-structures/base/index.ts
Normal file
|
@ -0,0 +1 @@
|
|||
export * from './base';
|
|
@ -9,3 +9,4 @@ export * from './queue';
|
|||
export * from './stack';
|
||||
export * from './tree';
|
||||
export * from './trie';
|
||||
export * from './base';
|
||||
|
|
|
@ -305,30 +305,30 @@ describe('AVLTree iterative methods test', () => {
|
|||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
avl.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
avl.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
expect(mockCallback.mock.calls[0]).toEqual(['a', 1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual(['b', 2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = avl.filter(([key]) => key > 1);
|
||||
const filteredTree = avl.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = avl.map(([key]) => (key * 2).toString());
|
||||
const mappedTree = avl.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = avl.reduce((acc, [key]) => acc + key, 0);
|
||||
const sum = avl.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
|
@ -350,11 +350,11 @@ describe('AVLTree iterative methods test', () => {
|
|||
|
||||
test('should keys', () => {
|
||||
const keys = avl.keys();
|
||||
expect(keys).toEqual([1, 2, 3]);
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
const values = avl.values();
|
||||
expect(values).toEqual(['a', 'b', 'c']);
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -580,30 +580,30 @@ describe('BinaryTree iterative methods test', () => {
|
|||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
binaryTree.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
binaryTree.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
expect(mockCallback.mock.calls[0]).toEqual(['b', 2]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual(['a', 1]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = binaryTree.filter(([key]) => key > 1);
|
||||
const filteredTree = binaryTree.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[3, 'c'], [2, 'b']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = binaryTree.map(([key]) => (key * 2).toString());
|
||||
const mappedTree = binaryTree.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = binaryTree.reduce((acc, [key]) => acc + key, 0);
|
||||
const sum = binaryTree.reduce((acc, currentValue, currentKey) => acc + currentKey, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
|
@ -625,11 +625,11 @@ describe('BinaryTree iterative methods test', () => {
|
|||
|
||||
test('should keys', () => {
|
||||
const keys = binaryTree.keys();
|
||||
expect(keys).toEqual([2, 1, 3]);
|
||||
expect([...keys]).toEqual([2, 1, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
const values = binaryTree.values();
|
||||
expect(values).toEqual(['b', 'a', 'c']);
|
||||
expect([...values]).toEqual(['b', 'a', 'c']);
|
||||
});
|
||||
});
|
|
@ -864,30 +864,30 @@ describe('BST iterative methods test', () => {
|
|||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
bst.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
bst.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
expect(mockCallback.mock.calls[0]).toEqual(['a', 1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual(['b', 2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = bst.filter(([key]) => key > 1);
|
||||
const filteredTree = bst.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = bst.map(([key]) => (key * 2).toString());
|
||||
const mappedTree = bst.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = bst.reduce((acc, [key]) => acc + key, 0);
|
||||
const sum = bst.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
|
@ -909,11 +909,11 @@ describe('BST iterative methods test', () => {
|
|||
|
||||
test('should keys', () => {
|
||||
const keys = bst.keys();
|
||||
expect(keys).toEqual([1, 2, 3]);
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
const values = bst.values();
|
||||
expect(values).toEqual(['a', 'b', 'c']);
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
|
@ -524,30 +524,30 @@ describe('RedBlackTree iterative methods test', () => {
|
|||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
rbTree.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
rbTree.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
expect(mockCallback.mock.calls[0]).toEqual(['a', 1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual(['b', 2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = rbTree.filter(([key]) => key > 1);
|
||||
const filteredTree = rbTree.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = rbTree.map(([key]) => (key * 2).toString());
|
||||
const mappedTree = rbTree.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = rbTree.reduce((acc, [key]) => acc + key, 0);
|
||||
const sum = rbTree.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
|
|
|
@ -619,30 +619,30 @@ describe('TreeMultimap iterative methods test', () => {
|
|||
|
||||
test('forEach should iterate over all elements', () => {
|
||||
const mockCallback = jest.fn();
|
||||
treeMM.forEach((entry) => {
|
||||
mockCallback(entry);
|
||||
treeMM.forEach((value, key) => {
|
||||
mockCallback(value, key);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0][0]).toEqual([1, 'a']);
|
||||
expect(mockCallback.mock.calls[1][0]).toEqual([2, 'b']);
|
||||
expect(mockCallback.mock.calls[2][0]).toEqual([3, 'c']);
|
||||
expect(mockCallback.mock.calls[0]).toEqual(['a', 1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual(['b', 2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
|
||||
});
|
||||
|
||||
test('filter should return a new tree with filtered elements', () => {
|
||||
const filteredTree = treeMM.filter(([key]) => key > 1);
|
||||
const filteredTree = treeMM.filter((value, key) => key > 1);
|
||||
expect(filteredTree.size).toBe(2);
|
||||
expect([...filteredTree]).toEqual([[2, 'b'], [3, 'c']]);
|
||||
});
|
||||
|
||||
test('map should return a new tree with modified elements', () => {
|
||||
const mappedTree = treeMM.map(([key]) => (key * 2).toString());
|
||||
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
|
||||
expect(mappedTree.size).toBe(3);
|
||||
expect([...mappedTree]).toEqual([[1, '2'], [2, '4'], [3, '6']]);
|
||||
});
|
||||
|
||||
test('reduce should accumulate values', () => {
|
||||
const sum = treeMM.reduce((acc, [key]) => acc + key, 0);
|
||||
const sum = treeMM.reduce((acc, value, key) => acc + key, 0);
|
||||
expect(sum).toBe(6);
|
||||
});
|
||||
|
||||
|
@ -665,11 +665,11 @@ describe('TreeMultimap iterative methods test', () => {
|
|||
|
||||
test('should keys', () => {
|
||||
const keys = treeMM.keys();
|
||||
expect(keys).toEqual([1, 2, 3]);
|
||||
expect([...keys]).toEqual([1, 2, 3]);
|
||||
});
|
||||
|
||||
test('should values', () => {
|
||||
const values = treeMM.values();
|
||||
expect(values).toEqual(['a', 'b', 'c']);
|
||||
expect([...values]).toEqual(['a', 'b', 'c']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -616,22 +616,22 @@ describe('DirectedGraph iterative Methods', () => {
|
|||
|
||||
test('forEach should apply a function to each vertex', () => {
|
||||
const result: VertexKey[] = [];
|
||||
graph.forEach(vertex => result.push(vertex[0]));
|
||||
graph.forEach((value, key) => key && result.push(key));
|
||||
expect(result).toEqual(vertices);
|
||||
});
|
||||
|
||||
test('filter should return vertices that satisfy the condition', () => {
|
||||
const filtered = graph.filter(vertex => vertex[0] === 'A' || vertex[0] === 'B');
|
||||
const filtered = graph.filter((value, vertex) => vertex === 'A' || vertex === 'B');
|
||||
expect(filtered).toEqual([["A", undefined], ["B", undefined]]);
|
||||
});
|
||||
|
||||
test('map should apply a function to each vertex and return a new array', () => {
|
||||
const mapped = graph.map(vertex => vertex[0] + '_mapped');
|
||||
const mapped = graph.map((value, vertex) => vertex + '_mapped');
|
||||
expect(mapped).toEqual(vertices.map(v => v + '_mapped'));
|
||||
});
|
||||
|
||||
test('reduce should accumulate a value based on each vertex', () => {
|
||||
const concatenated = graph.reduce((acc, vertex) => acc + vertex[0], '');
|
||||
const concatenated = graph.reduce((acc, value, key) => acc + key, '');
|
||||
expect(concatenated).toBe(vertices.join(''));
|
||||
});
|
||||
});
|
||||
|
|
|
@ -548,10 +548,10 @@ describe('LinkedHashMap setMany, keys, values', () => {
|
|||
})
|
||||
|
||||
test('keys', () => {
|
||||
expect(hm.keys()).toEqual([2, 3, 4, 5, 6])
|
||||
expect([...hm.keys()]).toEqual([2, 3, 4, 5, 6])
|
||||
});
|
||||
|
||||
test('values', () => {
|
||||
expect(hm.values()).toEqual([2, 3, 4, 5, 6])
|
||||
expect([...hm.values()]).toEqual([2, 3, 4, 5, 6])
|
||||
});
|
||||
});
|
|
@ -397,3 +397,31 @@ describe('DoublyLinkedList Operation Test', () => {
|
|||
expect(shiftedObj).toBe(obj1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('iterable methods', () => {
|
||||
it('should forEach, some, every, filter, map, reduce of the deque', () => {
|
||||
const dl = new DoublyLinkedList<number>()
|
||||
dl.push(1);
|
||||
dl.push(2);
|
||||
dl.push(3);
|
||||
|
||||
const mockCallback = jest.fn();
|
||||
dl.forEach((element) => {
|
||||
mockCallback(element);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0]).toEqual([1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual([2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual([3]);
|
||||
|
||||
expect(dl.every(element => element > 0)).toBe(true);
|
||||
expect(dl.every(element => element > 1)).toBe(false);
|
||||
expect(dl.some(element => element > 2)).toBe(true);
|
||||
|
||||
expect([...dl.filter(element => element > 2)]).toEqual([3]);
|
||||
expect([...dl.map(element => element * 2)]).toEqual([2, 4, 6]);
|
||||
expect(dl.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
||||
});
|
||||
});
|
|
@ -471,3 +471,28 @@ describe('SinglyLinkedList', () => {
|
|||
expect(list1.reduce((acc, value) => acc + value, 0)).toEqual(6);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe('iterable methods', () => {
|
||||
it('should forEach, some, every, filter, map, reduce of the deque', () => {
|
||||
const sl = new SinglyLinkedList<number>([1, 2, 3])
|
||||
|
||||
const mockCallback = jest.fn();
|
||||
sl.forEach((element) => {
|
||||
mockCallback(element);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0]).toEqual([1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual([2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual([3]);
|
||||
|
||||
expect(sl.every(element => element > 0)).toBe(true);
|
||||
expect(sl.every(element => element > 1)).toBe(false);
|
||||
expect(sl.some(element => element > 2)).toBe(true);
|
||||
|
||||
expect([...sl.filter(element => element > 2)]).toEqual([3]);
|
||||
expect([...sl.map(element => element * 2)]).toEqual([2, 4, 6]);
|
||||
expect(sl.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
||||
});
|
||||
});
|
|
@ -447,4 +447,29 @@ describe('Deque', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('iterable methods', () => {
|
||||
it('should forEach, some, every, filter, map, reduce of the deque', () => {
|
||||
deque.push(1);
|
||||
deque.push(2);
|
||||
deque.push(3);
|
||||
|
||||
const mockCallback = jest.fn();
|
||||
deque.forEach((element) => {
|
||||
mockCallback(element);
|
||||
});
|
||||
|
||||
expect(mockCallback.mock.calls.length).toBe(3);
|
||||
expect(mockCallback.mock.calls[0]).toEqual([1]);
|
||||
expect(mockCallback.mock.calls[1]).toEqual([2]);
|
||||
expect(mockCallback.mock.calls[2]).toEqual([3]);
|
||||
|
||||
expect(deque.every(element => element > 0)).toBe(true);
|
||||
expect(deque.every(element => element > 1)).toBe(false);
|
||||
expect(deque.some(element => element > 2)).toBe(true);
|
||||
|
||||
expect([...deque.filter(element => element > 2)]).toEqual([3]);
|
||||
expect([...deque.map(element => element * 2)]).toEqual([2, 4, 6]);
|
||||
expect(deque.reduce((accumulator, element) => accumulator + element, 0)).toEqual(6);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue