From 20550fb718625d4adb12f21fbe15c6ea9b074b47 Mon Sep 17 00:00:00 2001 From: Revone Date: Mon, 27 Nov 2023 11:24:23 +0800 Subject: [PATCH] feat: Implement the [Symbol.iterator], forEach, filter, map, and reduce methods for Graph, specifically targeting the nodes. fix: type error fixed --- CHANGELOG.md | 2 +- package.json | 2 +- src/data-structures/graph/abstract-graph.ts | 46 +++++++++++++++++++ src/data-structures/graph/directed-graph.ts | 2 +- test/integration/index.html | 4 +- .../linked-list/doubly-linked-list.test.ts | 2 +- .../linked-list/singly-linked-list.test.ts | 2 +- .../graph/directed-graph.test.ts | 41 +++++++++++++++++ 8 files changed, 94 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd554bb..4e70010 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ All notable changes to this project will be documented in this file. - [Semantic Versioning](https://semver.org/spec/v2.0.0.html) - [`auto-changelog`](https://github.com/CookPete/auto-changelog) -## [v1.47.7](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) +## [v1.47.8](https://github.com/zrwusa/data-structure-typed/compare/v1.35.0...main) (upcoming) ### Changes diff --git a/package.json b/package.json index bae6d62..52c08d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "data-structure-typed", - "version": "1.47.7", + "version": "1.47.8", "description": "Data Structures of Javascript & TypeScript. Heap, Binary Tree, RedBlack Tree, Linked List, Deque, Trie, HashMap, Directed Graph, Undirected Graph, Binary Search Tree(BST), AVL Tree, Priority Queue, Graph, Queue, Tree Multiset, Singly Linked List, Doubly Linked List, Max Heap, Max Priority Queue, Min Heap, Min Priority Queue, Stack.", "main": "dist/cjs/index.js", "module": "dist/mjs/index.js", diff --git a/src/data-structures/graph/abstract-graph.ts b/src/data-structures/graph/abstract-graph.ts index 70a03bb..7d7f5d2 100644 --- a/src/data-structures/graph/abstract-graph.ts +++ b/src/data-structures/graph/abstract-graph.ts @@ -1159,6 +1159,52 @@ 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]; + } + } + + forEach(callback: (entry: [VertexKey, V | undefined], index: number, map: Map) => 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) => boolean): [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); + } + index++; + } + return filtered; + } + + map(callback: (entry: [VertexKey, V | undefined], index: number, map: Map) => T): T[] { + const mapped: T[] = []; + let index = 0; + for (const entry of this) { + mapped.push(callback(entry, index, this._vertices)); + index++; + } + return mapped; + } + + reduce(callback: (accumulator: T, entry: [VertexKey, V | undefined], index: number, map: Map) => T, initialValue: T): T { + let accumulator: T = initialValue; + let index = 0; + for (const entry of this) { + accumulator = callback(accumulator, entry, index, this._vertices); + index++; + } + return accumulator; + } + protected abstract _addEdgeOnly(edge: EO): boolean; protected _addVertexOnly(newVertex: VO): boolean { diff --git a/src/data-structures/graph/directed-graph.ts b/src/data-structures/graph/directed-graph.ts index 3266732..3fd7839 100644 --- a/src/data-structures/graph/directed-graph.ts +++ b/src/data-structures/graph/directed-graph.ts @@ -87,7 +87,7 @@ export class DirectedGraph< * @returns a new instance of a DirectedVertex object, casted as type VO. */ createVertex(key: VertexKey, value?: V): VO { - return new DirectedVertex(key, value ?? key) as VO; + return new DirectedVertex(key, value) as VO; } /** diff --git a/test/integration/index.html b/test/integration/index.html index e0d984f..a7ecc3c 100644 --- a/test/integration/index.html +++ b/test/integration/index.html @@ -349,7 +349,7 @@ // 1 _4 6 _9 // / / // 3 8 - + const trie2 = new Trie(orgStrArr); trie2.print(); // ['trie', 'trial', 'triangle', 'trick', 'trip', 'tree', 'trend', 'track', 'trace', 'transmit'] @@ -367,7 +367,7 @@ // 0 2 _5_ 8_ // / \ \ // 4 6 9 - + } catch (e) { console.error(e); } diff --git a/test/performance/data-structures/linked-list/doubly-linked-list.test.ts b/test/performance/data-structures/linked-list/doubly-linked-list.test.ts index 042a4fa..1472ad7 100644 --- a/test/performance/data-structures/linked-list/doubly-linked-list.test.ts +++ b/test/performance/data-structures/linked-list/doubly-linked-list.test.ts @@ -57,7 +57,7 @@ suite }) .add(`${LINEAR.toLocaleString()} insertBefore`, () => { const doublyList = new DoublyLinkedList(); - let midNode: DoublyLinkedListNode | null = null; + let midNode: DoublyLinkedListNode | undefined; const midIndex = Math.floor(LINEAR / 2); for (let i = 0; i < LINEAR; i++) { doublyList.push(i); diff --git a/test/performance/data-structures/linked-list/singly-linked-list.test.ts b/test/performance/data-structures/linked-list/singly-linked-list.test.ts index 4d77b08..e1eaa6e 100644 --- a/test/performance/data-structures/linked-list/singly-linked-list.test.ts +++ b/test/performance/data-structures/linked-list/singly-linked-list.test.ts @@ -19,7 +19,7 @@ suite }) .add(`${TEN_THOUSAND.toLocaleString()} insertBefore`, () => { const singlyList = new SinglyLinkedList(); - let midSinglyNode: SinglyLinkedListNode | null = null; + let midSinglyNode: SinglyLinkedListNode | undefined; const midIndex = Math.floor(TEN_THOUSAND / 2); for (let i = 0; i < TEN_THOUSAND; i++) { singlyList.push(i); diff --git a/test/unit/data-structures/graph/directed-graph.test.ts b/test/unit/data-structures/graph/directed-graph.test.ts index 44e63b9..f0b3281 100644 --- a/test/unit/data-structures/graph/directed-graph.test.ts +++ b/test/unit/data-structures/graph/directed-graph.test.ts @@ -595,3 +595,44 @@ describe('cycles, strongly connected components, bridges, articular points in Di expect(dfnMap.size).toBe(8); expect(lowMap.size).toBe(8); }); + +describe('DirectedGraph iterative Methods', () => { + let graph: DirectedGraph; + let vertices: string[]; + + beforeEach(() => { + graph = new DirectedGraph(); + vertices = ['A', 'B', 'C', 'D']; + vertices.forEach(vertex => graph.addVertex(vertex)); + }); + + test('[Symbol.iterator] should iterate over all vertices', () => { + const iteratedVertices = []; + for (const vertex of graph) { + iteratedVertices.push(vertex[0]); + } + expect(iteratedVertices).toEqual(vertices); + }); + + test('forEach should apply a function to each vertex', () => { + const result: VertexKey[] = []; + graph.forEach(vertex => result.push(vertex[0])); + expect(result).toEqual(vertices); + }); + + test('filter should return vertices that satisfy the condition', () => { + const filtered = graph.filter(vertex => vertex[0] === 'A' || vertex[0] === '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'); + 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], ''); + expect(concatenated).toBe(vertices.join('')); + }); +}); +