Skip to content

Commit

Permalink
test: The test cases have been added, though slightly tricky. The ove…
Browse files Browse the repository at this point in the history
…rall test coverage is currently at 93.27%.
  • Loading branch information
zrwusa committed Oct 16, 2024
1 parent e6acc0f commit 07dd75d
Show file tree
Hide file tree
Showing 28 changed files with 1,024 additions and 352 deletions.
82 changes: 28 additions & 54 deletions src/data-structures/hash/hash-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,8 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
if (this.isEntry(rawEle)) {
key = rawEle[0];
value = rawEle[1];
} else if (this.toEntryFn) {
const item = this.toEntryFn(rawEle);
} else if (this._toEntryFn) {
const item = this._toEntryFn(rawEle);
key = item[0];
value = item[1];
}
Expand Down Expand Up @@ -244,7 +244,7 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
* @return A new hashmap with the same values as this one
*/
clone(): HashMap<K, V, R> {
return new HashMap<K, V, R>(this, { hashFn: this.hashFn, toEntryFn: this.toEntryFn });
return new HashMap<K, V, R>(this, { hashFn: this._hashFn, toEntryFn: this._toEntryFn });
}

/**
Expand Down Expand Up @@ -302,18 +302,6 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,
return filteredMap;
}

/**
* The put function sets a value in a data structure using a specified key.
* @param {K} key - The key parameter is of type K, which represents the type of the key being passed
* to the function.
* @param {V} value - The value parameter represents the value that you want to associate with the
* specified key in the data structure.
* @returns The method is returning a boolean value.
*/
put(key: K, value: V): boolean {
return this.set(key, value);
}

/**
* The function returns an iterator that yields key-value pairs from both an object store and an
* object map.
Expand Down Expand Up @@ -349,7 +337,7 @@ export class HashMap<K = any, V = any, R = [K, V]> extends IterableEntryBase<K,

let strKey: string;
if (keyType !== 'string' && keyType !== 'number' && keyType !== 'symbol') {
strKey = this.hashFn(key);
strKey = this._hashFn(key);
} else {
if (keyType === 'number') {
// TODO numeric key should has its own hash
Expand Down Expand Up @@ -379,7 +367,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
* @param [options] - The `options` parameter is an optional object that can contain the following
* properties:
*/
constructor(entryOrRawElements: Iterable<R> = [], options?: LinkedHashMapOptions<K, V, R>) {
constructor(entryOrRawElements: Iterable<R | [K, V]> = [], options?: LinkedHashMapOptions<K, V, R>) {
super();
this._sentinel = <HashMapLinkedNode<K, V>>{};
this._sentinel.prev = this._sentinel.next = this._head = this._tail = this._sentinel;
Expand All @@ -395,10 +383,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
}

if (entryOrRawElements) {
for (const el of entryOrRawElements) {
const [key, value] = this.toEntryFn(el);
this.set(key, value);
}
this.setMany(entryOrRawElements);
}
}

Expand Down Expand Up @@ -465,7 +450,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
return this._tail;
}

protected _toEntryFn: (rawElement: R) => [K, V] = (rawElement: R) => {
protected _toEntryFn?: (rawElement: R) => [K, V] = (rawElement: R) => {
if (this.isEntry(rawElement)) {
// TODO, For performance optimization, it may be necessary to only inspect the first element traversed.
return rawElement;
Expand Down Expand Up @@ -575,7 +560,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
const isNewKey = !this.has(key); // Check if the key is new

if (isWeakKey(key)) {
const hash = this.objHashFn(key);
const hash = this._objHashFn(key);
node = this.objMap.get(hash);

if (!node && isNewKey) {
Expand All @@ -587,7 +572,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
node.value = value;
}
} else {
const hash = this.hashFn(key);
const hash = this._hashFn(key);
node = this.noObjMap[hash];

if (!node && isNewKey) {
Expand Down Expand Up @@ -623,11 +608,20 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
* R.
* @returns The `setMany` function returns an array of booleans.
*/
setMany(entryOrRawElements: Iterable<R>): boolean[] {
setMany(entryOrRawElements: Iterable<R | [K, V]>): boolean[] {
const results: boolean[] = [];
for (const rawEle of entryOrRawElements) {
const [key, value] = this.toEntryFn(rawEle);
results.push(this.set(key, value));
let key: K | undefined, value: V | undefined;
if (this.isEntry(rawEle)) {
key = rawEle[0];
value = rawEle[1];
} else if (this._toEntryFn) {
const item = this._toEntryFn(rawEle);
key = item[0];
value = item[1];
}

if (key !== undefined && value !== undefined) results.push(this.set(key, value));
}
return results;
}
Expand All @@ -640,10 +634,10 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
*/
override has(key: K): boolean {
if (isWeakKey(key)) {
const hash = this.objHashFn(key);
const hash = this._objHashFn(key);
return this.objMap.has(hash);
} else {
const hash = this.hashFn(key);
const hash = this._hashFn(key);
return hash in this.noObjMap;
}
}
Expand All @@ -668,11 +662,11 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
*/
override get(key: K): V | undefined {
if (isWeakKey(key)) {
const hash = this.objHashFn(key);
const hash = this._objHashFn(key);
const node = this.objMap.get(hash);
return node ? node.value : undefined;
} else {
const hash = this.hashFn(key);
const hash = this._hashFn(key);
const node = this.noObjMap[hash];
return node ? node.value : undefined;
}
Expand Down Expand Up @@ -722,7 +716,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
let node;

if (isWeakKey(key)) {
const hash = this.objHashFn(key);
const hash = this._objHashFn(key);
// Get nodes from WeakMap
node = this.objMap.get(hash);

Expand All @@ -733,7 +727,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
// Remove nodes from WeakMap
this.objMap.delete(hash);
} else {
const hash = this.hashFn(key);
const hash = this._hashFn(key);
// Get nodes from noObjMap
node = this.noObjMap[hash];

Expand Down Expand Up @@ -832,7 +826,7 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
* of the original `LinkedHashMap` object.
*/
clone(): LinkedHashMap<K, V> {
const cloned = new LinkedHashMap<K, V>([], { hashFn: this.hashFn, objHashFn: this.objHashFn });
const cloned = new LinkedHashMap<K, V>([], { hashFn: this._hashFn, objHashFn: this._objHashFn });
for (const entry of this) {
const [key, value] = entry;
cloned.set(key, value);
Expand Down Expand Up @@ -905,26 +899,6 @@ export class LinkedHashMap<K = any, V = any, R = [K, V]> extends IterableEntryBa
return mappedMap;
}

/**
* Time Complexity: O(1)
* Space Complexity: O(1)
*/

/**
* Time Complexity: O(1)
* Space Complexity: O(1)
*
* The put function sets a value in a data structure using a specified key.
* @param {K} key - The key parameter is of type K, which represents the type of the key being passed
* to the function.
* @param {V} value - The value parameter represents the value that you want to associate with the
* specified key in the data structure.
* @returns The method is returning a boolean value.
*/
put(key: K, value: V): boolean {
return this.set(key, value);
}

/**
* Time Complexity: O(n)
* Space Complexity: O(1)
Expand Down
2 changes: 1 addition & 1 deletion src/data-structures/linked-list/singly-linked-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ export class SinglyLinkedList<E = any, R = any> extends IterableElementBase<E, R
* successfully deleted from the linked list, and `false` if the value or node is not found in the linked list.
*/
delete(valueOrNode: E | SinglyLinkedListNode<E> | undefined): boolean {
if (!valueOrNode) return false;
if (valueOrNode === undefined) return false;
let value: E;
if (valueOrNode instanceof SinglyLinkedListNode) {
value = valueOrNode.value;
Expand Down
3 changes: 1 addition & 2 deletions src/data-structures/queue/deque.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,6 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
cutRest(pos: number, isCutSelf = false): Deque<E> {
if (isCutSelf) {
if (pos < 0) {
this.clear();
return this;
}
const { bucketIndex, indexInBucket } = this._getBucketAndPosition(pos);
Expand All @@ -517,7 +516,7 @@ export class Deque<E = any, R = any> extends IterableElementBase<E, R, Deque<E,
return this;
} else {
const newDeque = new Deque<E>([], { bucketSize: this._bucketSize });

if (pos < 0) pos = 0;
for (let i = pos; i < this.size; i++) {
newDeque.push(this.at(i));
}
Expand Down
2 changes: 1 addition & 1 deletion src/data-structures/queue/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export class Queue<E = any, R = any> extends IterableElementBase<E, R, Queue<E,
return this.size > 0 ? this.elements[this.elements.length - 1] : undefined;
}

_autoCompactRatio: number = 0.5;
protected _autoCompactRatio: number = 0.5;

/**
* This function returns the value of the autoCompactRatio property.
Expand Down
1 change: 0 additions & 1 deletion src/data-structures/tree/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ export class TreeNode<V = any> {
constructor(key: string, value?: V, children?: TreeNode<V>[]) {
this._key = key;
this._value = value || undefined;
this._children = children || [];
}

protected _key: string;
Expand Down
18 changes: 9 additions & 9 deletions test/unit/data-structures/binary-tree/avl-tree-multi-map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,14 +617,14 @@ describe('AVLTreeMultiMap iterative methods test', () => {
treeMM.add([3, 'c'], undefined, 1);
});

test('The node obtained by get Node should match the node type', () => {
it('The node obtained by get Node should match the node type', () => {
const node3 = treeMM.getNode(3);
expect(node3).toBeInstanceOf(BinaryTreeNode);
expect(node3).toBeInstanceOf(BSTNode);
expect(node3).toBeInstanceOf(AVLTreeNode);
});

test('forEach should iterate over all elements', () => {
it('forEach should iterate over all elements', () => {
const mockCallback = jest.fn();
treeMM.forEach((value, key) => {
mockCallback(value, key);
Expand All @@ -636,7 +636,7 @@ describe('AVLTreeMultiMap iterative methods test', () => {
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
});

test('filter should return a new tree with filtered elements', () => {
it('filter should return a new tree with filtered elements', () => {
const filteredTree = treeMM.filter((value, key) => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
Expand All @@ -645,7 +645,7 @@ describe('AVLTreeMultiMap iterative methods test', () => {
]);
});

test('map should return a new tree with modified elements', () => {
it('map should return a new tree with modified elements', () => {
const mappedTree = treeMM.map((value, key) => (key * 2).toString());
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
Expand All @@ -655,12 +655,12 @@ describe('AVLTreeMultiMap iterative methods test', () => {
]);
});

test('reduce should accumulate values', () => {
it('reduce should accumulate values', () => {
const sum = treeMM.reduce((acc, value, key) => acc + key, 0);
expect(sum).toBe(6);
});

test('[Symbol.iterator] should provide an iterator', () => {
it('[Symbol.iterator] should provide an iterator', () => {
const entries = [];
for (const entry of treeMM) {
entries.push(entry);
Expand All @@ -674,19 +674,19 @@ describe('AVLTreeMultiMap iterative methods test', () => {
]);
});

test('should clone work well', () => {
it('should clone work well', () => {
expect(treeMM.count).toBe(21);
const cloned = treeMM.clone();
expect(cloned.root?.left?.key).toBe(1);
expect(cloned.root?.right?.value).toBe('c');
});

test('should keys', () => {
it('should keys', () => {
const keys = treeMM.keys();
expect([...keys]).toEqual([1, 2, 3]);
});

test('should values', () => {
it('should values', () => {
const values = treeMM.values();
expect([...values]).toEqual(['a', 'b', 'c']);
});
Expand Down
18 changes: 9 additions & 9 deletions test/unit/data-structures/binary-tree/avl-tree.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,14 +339,14 @@ describe('AVLTree iterative methods test', () => {
avl.add([3, 'c']);
});

test('The node obtained by get Node should match the node type', () => {
it('The node obtained by get Node should match the node type', () => {
const node3 = avl.getNode(3);
expect(node3).toBeInstanceOf(BinaryTreeNode);
expect(node3).toBeInstanceOf(BSTNode);
expect(node3).toBeInstanceOf(AVLTreeNode);
});

test('forEach should iterate over all elements', () => {
it('forEach should iterate over all elements', () => {
const mockCallback = jest.fn();
avl.forEach((value, key) => {
mockCallback(value, key);
Expand All @@ -358,7 +358,7 @@ describe('AVLTree iterative methods test', () => {
expect(mockCallback.mock.calls[2]).toEqual(['c', 3]);
});

test('filter should return a new tree with filtered elements', () => {
it('filter should return a new tree with filtered elements', () => {
const filteredTree = avl.filter((value, key) => key > 1);
expect(filteredTree.size).toBe(2);
expect([...filteredTree]).toEqual([
Expand All @@ -367,7 +367,7 @@ describe('AVLTree iterative methods test', () => {
]);
});

test('map should return a new tree with modified elements', () => {
it('map should return a new tree with modified elements', () => {
const mappedTree = avl.map((value, key) => (key * 2).toString());
expect(mappedTree.size).toBe(3);
expect([...mappedTree]).toEqual([
Expand All @@ -377,12 +377,12 @@ describe('AVLTree iterative methods test', () => {
]);
});

test('reduce should accumulate values', () => {
it('reduce should accumulate values', () => {
const sum = avl.reduce((acc, value, key) => acc + key, 0);
expect(sum).toBe(6);
});

test('[Symbol.iterator] should provide an iterator', () => {
it('[Symbol.iterator] should provide an iterator', () => {
const entries = [];
for (const entry of avl) {
entries.push(entry);
Expand All @@ -396,18 +396,18 @@ describe('AVLTree iterative methods test', () => {
]);
});

test('should clone work well', () => {
it('should clone work well', () => {
const cloned = avl.clone();
expect(cloned.root?.left?.key).toBe(1);
expect(cloned.root?.right?.value).toBe('c');
});

test('should keys', () => {
it('should keys', () => {
const keys = avl.keys();
expect([...keys]).toEqual([1, 2, 3]);
});

test('should values', () => {
it('should values', () => {
const values = avl.values();
expect([...values]).toEqual(['a', 'b', 'c']);
});
Expand Down
Loading

0 comments on commit 07dd75d

Please sign in to comment.