tree-processor 0.9.7 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +759 -39
- package/README.md +759 -40
- package/dist/.tsbuildinfo +1 -1
- package/dist/index.d.ts +95 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/stats.html +1 -1
- package/dist/tree-processor.cjs.js +116 -38
- package/dist/tree-processor.esm.js +117 -39
- package/dist/tree-processor.umd.js +174 -96
- package/package.json +4 -2
package/README.en.md
CHANGED
|
@@ -9,12 +9,12 @@
|
|
|
9
9
|
<div align="center">
|
|
10
10
|
|
|
11
11
|

|
|
12
|
-
](https://img.shields.io/badge/downloads-1.7K%2F2mo-brightgreen?style=flat-square)
|
|
13
|
+

|
|
14
14
|

|
|
15
15
|

|
|
16
16
|
|
|
17
|
-
A lightweight tree-structured data processing utility library written in TypeScript,
|
|
17
|
+
A lightweight tree-structured data processing utility library written in TypeScript, providing 50+ APIs including traversal, search, modification, conversion, query, analysis, and validation.
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
</div>
|
|
@@ -26,28 +26,26 @@ A lightweight tree-structured data processing utility library written in TypeScr
|
|
|
26
26
|
- [Installation](#-installation)
|
|
27
27
|
- [Quick Start](#-quick-start)
|
|
28
28
|
- [API Documentation](#-api-documentation)
|
|
29
|
-
- [Traversal Methods](#traversal-methods)
|
|
30
|
-
- [Search Methods](#search-methods)
|
|
31
|
-
- [Access Methods](#access-methods)
|
|
32
|
-
- [
|
|
33
|
-
- [Conversion Methods](#conversion-methods)
|
|
34
|
-
- [
|
|
35
|
-
- [
|
|
29
|
+
- [Traversal Operation Methods](#traversal-operation-methods)
|
|
30
|
+
- [Conditional Search Methods](#conditional-search-methods)
|
|
31
|
+
- [Index Access Methods](#index-access-methods)
|
|
32
|
+
- [Node Operation Methods](#node-operation-methods)
|
|
33
|
+
- [Format Conversion Methods](#format-conversion-methods)
|
|
34
|
+
- [Clone and Copy Methods](#clone-and-copy-methods)
|
|
35
|
+
- [Relationship Query Methods](#relationship-query-methods)
|
|
36
|
+
- [Data Validation Methods](#data-validation-methods)
|
|
37
|
+
- [Aggregation Analysis Methods](#aggregation-analysis-methods)
|
|
36
38
|
- [Custom Field Names](#custom-field-names)
|
|
37
39
|
- [Testing](#testing)
|
|
38
40
|
- [Development](#development)
|
|
39
41
|
|
|
40
42
|
## ✨ Features
|
|
41
43
|
|
|
42
|
-
- **
|
|
43
|
-
- **
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
47
|
-
- **Comprehensive Test Coverage** - Contains 328 test cases with 99%+ test coverage (99% statement coverage, 98.41% branch coverage, 100% function coverage, 98.99% line coverage), covering basic functionality, edge cases, error handling, and complex scenarios
|
|
48
|
-
- **Rich API** - Provides 32+ methods, including array-like APIs (map, filter, find, some, every, includes, at, indexOf, etc.), and tree-specific operations (get parent/child nodes, depth calculation, data validation, format conversion, etc.), covering complete scenarios for traversal, search, modification, conversion, and validation
|
|
49
|
-
|
|
50
|
-
**Supported methods:** mapTree, forEachTree, filterTree, findTree, pushTree, unshiftTree, popTree, shiftTree, someTree, everyTree, includesTree, atTree, indexOfTree, atIndexOfTree, dedupTree, removeTree, getParentTree, getChildrenTree, getSiblingsTree, getNodeDepthMap, getNodeDepth, isLeafNode, isRootNode, isEmptyTreeData, isEmptySingleTreeData, isTreeData, isSingleTreeData, isValidTreeNode, isTreeNodeWithCircularCheck, isSafeTreeDepth, convertToArrayTree, convertBackTree, convertToMapTree, convertToLevelArrayTree, convertToObjectTree. The last parameter of each method can customize the property names for children and id.
|
|
44
|
+
- **Multiple Format Support** - Provides ESM, CJS, UMD formats, bundle size only 14.9-15.2 KB, supports Tree-shaking, on-demand imports
|
|
45
|
+
- **Zero Dependencies** - No external dependencies, ready to use
|
|
46
|
+
- **High Performance** - Average execution time < 0.03ms on medium-sized trees (~120 nodes)
|
|
47
|
+
- **Complete Functionality** - 50+ APIs covering traversal, search, modification, conversion, query, analysis, and validation
|
|
48
|
+
- **Comprehensive Testing** - 447 test cases with 99%+ coverage
|
|
51
49
|
|
|
52
50
|
### 💡 Use Cases
|
|
53
51
|
|
|
@@ -153,7 +151,9 @@ const treeData = [
|
|
|
153
151
|
|
|
154
152
|
---
|
|
155
153
|
|
|
156
|
-
## Traversal Methods
|
|
154
|
+
## Traversal Operation Methods
|
|
155
|
+
|
|
156
|
+
Methods for traversing tree-structured data and performing operations on each node.
|
|
157
157
|
|
|
158
158
|
### mapTree
|
|
159
159
|
|
|
@@ -202,7 +202,9 @@ console.log(nodeCount) // Total number of nodes
|
|
|
202
202
|
|
|
203
203
|
---
|
|
204
204
|
|
|
205
|
-
## Search Methods
|
|
205
|
+
## Conditional Search Methods
|
|
206
|
+
|
|
207
|
+
Methods for finding nodes by conditions or predicate functions.
|
|
206
208
|
|
|
207
209
|
### filterTree
|
|
208
210
|
|
|
@@ -285,7 +287,9 @@ console.log(allHaveName) // Returns true or false based on actual data
|
|
|
285
287
|
|
|
286
288
|
---
|
|
287
289
|
|
|
288
|
-
## Access Methods
|
|
290
|
+
## Index Access Methods
|
|
291
|
+
|
|
292
|
+
Methods for accessing nodes by position index or index path.
|
|
289
293
|
|
|
290
294
|
### atTree
|
|
291
295
|
|
|
@@ -345,7 +349,9 @@ console.log(invalidPath) // null
|
|
|
345
349
|
|
|
346
350
|
---
|
|
347
351
|
|
|
348
|
-
##
|
|
352
|
+
## Node Operation Methods
|
|
353
|
+
|
|
354
|
+
Methods for adding, removing, and modifying nodes in tree structures.
|
|
349
355
|
|
|
350
356
|
### pushTree
|
|
351
357
|
|
|
@@ -375,26 +381,30 @@ console.log(treeData) // New node has been added to the beginning of the childre
|
|
|
375
381
|
|
|
376
382
|
### popTree
|
|
377
383
|
|
|
378
|
-
Remove the last child node under the specified node. Returns the removed node, or
|
|
384
|
+
Remove the last child node under the specified node. Returns the removed node, or null if the node doesn't exist or has no children.
|
|
379
385
|
|
|
380
386
|
```javascript
|
|
381
387
|
// Remove the last child node under the node with ID 1
|
|
382
388
|
const removedNode = t.popTree(treeData, 1)
|
|
383
|
-
console.log(removedNode) // Returns the removed node object, or
|
|
389
|
+
console.log(removedNode) // Returns the removed node object, or null
|
|
384
390
|
|
|
385
391
|
// Try to remove from a non-existent node
|
|
386
392
|
const popFailed = t.popTree(treeData, 999)
|
|
387
|
-
console.log(popFailed) //
|
|
393
|
+
console.log(popFailed) // null
|
|
388
394
|
```
|
|
389
395
|
|
|
390
396
|
### shiftTree
|
|
391
397
|
|
|
392
|
-
Remove the first child node under the specified node. Returns the removed node, or
|
|
398
|
+
Remove the first child node under the specified node. Returns the removed node, or null if the node doesn't exist or has no children.
|
|
393
399
|
|
|
394
400
|
```javascript
|
|
395
401
|
// Remove the first child node under the node with ID 1
|
|
396
402
|
const shiftedNode = t.shiftTree(treeData, 1)
|
|
397
|
-
console.log(shiftedNode) // Returns the removed node object, or
|
|
403
|
+
console.log(shiftedNode) // Returns the removed node object, or null
|
|
404
|
+
|
|
405
|
+
// Try to remove from a non-existent node
|
|
406
|
+
const shiftFailed = t.shiftTree(treeData, 999)
|
|
407
|
+
console.log(shiftFailed) // null
|
|
398
408
|
```
|
|
399
409
|
|
|
400
410
|
### removeTree
|
|
@@ -409,23 +419,138 @@ console.log(removeSuccess) // true means successful removal, false means node no
|
|
|
409
419
|
console.log(treeData) // Tree structure after removal
|
|
410
420
|
```
|
|
411
421
|
|
|
422
|
+
### concatTree
|
|
423
|
+
|
|
424
|
+
Concatenate multiple tree-structured data arrays, returns a new concatenated tree (deep cloned).
|
|
425
|
+
|
|
426
|
+
```javascript
|
|
427
|
+
const tree1 = [
|
|
428
|
+
{ id: 1, name: 'node1' },
|
|
429
|
+
{ id: 2, name: 'node2' }
|
|
430
|
+
]
|
|
431
|
+
const tree2 = [
|
|
432
|
+
{ id: 3, name: 'node3' }
|
|
433
|
+
]
|
|
434
|
+
|
|
435
|
+
// Concatenate multiple trees
|
|
436
|
+
const result = t.concatTree(tree1, tree2)
|
|
437
|
+
console.log(result) // [{ id: 1, name: 'node1' }, { id: 2, name: 'node2' }, { id: 3, name: 'node3' }]
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
**Parameters:**
|
|
441
|
+
- `...trees`: Multiple tree-structured data arrays (variadic arguments)
|
|
442
|
+
|
|
443
|
+
**Notes:**
|
|
444
|
+
- All trees are deep cloned, won't modify the original trees
|
|
445
|
+
- Supports concatenating any number of tree structures
|
|
446
|
+
|
|
447
|
+
### sortTree
|
|
448
|
+
|
|
449
|
+
Sort tree-structured data, recursively sorts all levels.
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
const tree = [
|
|
453
|
+
{ id: 3, name: 'node3' },
|
|
454
|
+
{ id: 1, name: 'node1' },
|
|
455
|
+
{ id: 2, name: 'node2' }
|
|
456
|
+
]
|
|
457
|
+
|
|
458
|
+
// Sort by id
|
|
459
|
+
const sorted = t.sortTree(tree, (a, b) => a.id - b.id)
|
|
460
|
+
console.log(sorted)
|
|
461
|
+
// [{ id: 1, name: 'node1' }, { id: 2, name: 'node2' }, { id: 3, name: 'node3' }]
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
**Parameters:**
|
|
465
|
+
- `tree`: Tree-structured data
|
|
466
|
+
- `compareFn`: Comparison function, same as `Array.sort`'s `compareFn` (optional)
|
|
467
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
468
|
+
|
|
469
|
+
**Notes:**
|
|
470
|
+
- Recursively sorts nodes at all levels
|
|
471
|
+
- Returns a new sorted tree (deep cloned), won't modify the original tree
|
|
472
|
+
- Uses default sorting if `compareFn` is not provided
|
|
473
|
+
|
|
474
|
+
### sliceTree
|
|
475
|
+
|
|
476
|
+
Slice the root nodes of tree-structured data (similar to array's `slice`).
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
const tree = [
|
|
480
|
+
{ id: 1, name: 'node1' },
|
|
481
|
+
{ id: 2, name: 'node2' },
|
|
482
|
+
{ id: 3, name: 'node3' }
|
|
483
|
+
]
|
|
484
|
+
|
|
485
|
+
// Slice: get nodes from index 1 to 3
|
|
486
|
+
const sliced = t.sliceTree(tree, 1, 3)
|
|
487
|
+
console.log(sliced) // [{ id: 2, name: 'node2' }, { id: 3, name: 'node3' }]
|
|
488
|
+
|
|
489
|
+
// Supports negative indices
|
|
490
|
+
const lastTwo = t.sliceTree(tree, -2)
|
|
491
|
+
console.log(lastTwo) // [{ id: 2, name: 'node2' }, { id: 3, name: 'node3' }]
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
**Parameters:**
|
|
495
|
+
- `tree`: Tree-structured data
|
|
496
|
+
- `start`: Start index (inclusive), optional
|
|
497
|
+
- `end`: End index (exclusive), optional
|
|
498
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
499
|
+
|
|
500
|
+
**Notes:**
|
|
501
|
+
- Only slices root nodes, doesn't recursively process children
|
|
502
|
+
- Returns a new sliced tree (deep cloned), won't modify the original tree
|
|
503
|
+
- Supports negative indices (calculated from the end)
|
|
504
|
+
- Child node structures are completely preserved
|
|
505
|
+
|
|
412
506
|
### dedupTree
|
|
413
507
|
|
|
414
|
-
Tree-structured object array deduplication method that removes duplicate nodes based on the specified key. Keeps the first occurrence of the node.
|
|
508
|
+
Tree-structured object array deduplication method that removes duplicate nodes based on the specified key. Keeps the first occurrence of the node. Supports single field, multiple fields combined deduplication, and custom functions.
|
|
509
|
+
|
|
510
|
+
**Parameters:**
|
|
511
|
+
- `tree`: Tree-structured data
|
|
512
|
+
- `key`: Key(s) for deduplication, supports three types:
|
|
513
|
+
- `string`: Single field deduplication (e.g., `'id'`)
|
|
514
|
+
- `string[]`: Multiple fields combined deduplication (e.g., `['id', 'type']`)
|
|
515
|
+
- `(node: TreeNode) => any`: Custom function that returns the value for deduplication
|
|
516
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
415
517
|
|
|
416
518
|
```javascript
|
|
417
|
-
//
|
|
519
|
+
// Method 1: Single field deduplication (original usage)
|
|
418
520
|
const uniqueTreeData = t.dedupTree(treeData, 'id')
|
|
419
521
|
console.log(uniqueTreeData) // Returns deduplicated tree-structured data
|
|
420
522
|
|
|
421
|
-
//
|
|
422
|
-
const
|
|
423
|
-
|
|
523
|
+
// Method 2: Multiple fields combined deduplication (new feature)
|
|
524
|
+
const tree = [
|
|
525
|
+
{
|
|
526
|
+
id: 1,
|
|
527
|
+
children: [
|
|
528
|
+
{ id: 2, type: 'A', name: 'node1' },
|
|
529
|
+
{ id: 2, type: 'B', name: 'node2' }, // Kept (same id but different type)
|
|
530
|
+
{ id: 2, type: 'A', name: 'node3' }, // Deduplicated (both id and type are same)
|
|
531
|
+
]
|
|
532
|
+
}
|
|
533
|
+
]
|
|
534
|
+
const uniqueByMultiFields = t.dedupTree(tree, ['id', 'type'])
|
|
535
|
+
// Result: Keeps node1 and node2, node3 is deduplicated
|
|
536
|
+
|
|
537
|
+
// Method 3: Custom function deduplication
|
|
538
|
+
const uniqueByCustom = t.dedupTree(treeData, (node) => node.code)
|
|
539
|
+
// Or more complex logic
|
|
540
|
+
const uniqueByComplex = t.dedupTree(treeData, (node) => `${node.id}-${node.type}`)
|
|
424
541
|
```
|
|
425
542
|
|
|
543
|
+
**Notes:**
|
|
544
|
+
- If the dedupKey value is `undefined` or `null`, the node will not be deduplicated (all will be kept)
|
|
545
|
+
- Multiple fields combined deduplication uses the combination of field values to determine duplicates
|
|
546
|
+
- Recursively processes all levels of child nodes
|
|
547
|
+
- **Performance Optimization**: Multiple fields combined deduplication has been optimized, using efficient delimiter concatenation instead of JSON.stringify for better performance
|
|
548
|
+
|
|
426
549
|
---
|
|
427
550
|
|
|
428
|
-
## Conversion Methods
|
|
551
|
+
## Format Conversion Methods
|
|
552
|
+
|
|
553
|
+
Methods for converting between different data formats (array, Map, object, etc.).
|
|
429
554
|
|
|
430
555
|
### convertToArrayTree
|
|
431
556
|
|
|
@@ -699,7 +824,169 @@ console.log(treeFromRecord) // Correctly converted to tree structure
|
|
|
699
824
|
|
|
700
825
|
---
|
|
701
826
|
|
|
702
|
-
##
|
|
827
|
+
## Clone and Copy Methods
|
|
828
|
+
|
|
829
|
+
Methods for copying tree-structured data (deep copy, shallow copy, subtree copy, etc.).
|
|
830
|
+
|
|
831
|
+
### cloneTree
|
|
832
|
+
|
|
833
|
+
Deep clone tree-structured data, returns a completely independent copy without modifying the original tree.
|
|
834
|
+
|
|
835
|
+
```javascript
|
|
836
|
+
const original = [
|
|
837
|
+
{ id: 1, name: 'node1', children: [{ id: 2, name: 'node2' }] }
|
|
838
|
+
]
|
|
839
|
+
|
|
840
|
+
// Deep clone
|
|
841
|
+
const cloned = t.cloneTree(original)
|
|
842
|
+
|
|
843
|
+
// Modifying the cloned tree won't affect the original
|
|
844
|
+
cloned[0].name = 'modified'
|
|
845
|
+
console.log(original[0].name) // 'node1'
|
|
846
|
+
console.log(cloned[0].name) // 'modified'
|
|
847
|
+
```
|
|
848
|
+
|
|
849
|
+
**Parameters:**
|
|
850
|
+
- `tree`: Tree-structured data
|
|
851
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
852
|
+
|
|
853
|
+
**Notes:**
|
|
854
|
+
- Recursively deep clones all levels of nodes and children
|
|
855
|
+
- Returns a tree completely independent from the original, modifications won't affect each other
|
|
856
|
+
- Supports custom field name configuration
|
|
857
|
+
|
|
858
|
+
### shallowCloneTree
|
|
859
|
+
|
|
860
|
+
Shallow clone tree-structured data (only copies the first level, children share references). Better performance than deep clone, suitable for scenarios where only the top-level structure needs to be copied.
|
|
861
|
+
|
|
862
|
+
```javascript
|
|
863
|
+
const original = [
|
|
864
|
+
{ id: 1, name: 'node1', children: [{ id: 2, name: 'node2' }] }
|
|
865
|
+
]
|
|
866
|
+
|
|
867
|
+
// Shallow clone
|
|
868
|
+
const cloned = t.shallowCloneTree(original)
|
|
869
|
+
|
|
870
|
+
// Modifying the first level won't affect the original
|
|
871
|
+
cloned[0].name = 'modified'
|
|
872
|
+
console.log(original[0].name) // 'node1'
|
|
873
|
+
|
|
874
|
+
// But children share references, modifying children will affect the original
|
|
875
|
+
cloned[0].children[0].name = 'changed'
|
|
876
|
+
console.log(original[0].children[0].name) // 'changed'
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
**Parameters:**
|
|
880
|
+
- `tree`: Tree-structured data
|
|
881
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
882
|
+
|
|
883
|
+
**Notes:**
|
|
884
|
+
- Only copies the first level of nodes, children maintain shared references
|
|
885
|
+
- Better performance than deep clone, suitable for scenarios where only top-level independence is needed
|
|
886
|
+
- Modifying children will affect the original tree
|
|
887
|
+
|
|
888
|
+
### cloneSubtree
|
|
889
|
+
|
|
890
|
+
Clone a subtree starting from the specified node. Returns a deep copy containing the target node and all its children. Supports finding nodes by any field.
|
|
891
|
+
|
|
892
|
+
```javascript
|
|
893
|
+
const tree = [
|
|
894
|
+
{
|
|
895
|
+
id: 1,
|
|
896
|
+
name: 'root',
|
|
897
|
+
children: [
|
|
898
|
+
{ id: 2, name: 'sub1', children: [{ id: 4, name: 'sub1-1' }] },
|
|
899
|
+
{ id: 3, name: 'sub2' }
|
|
900
|
+
]
|
|
901
|
+
}
|
|
902
|
+
]
|
|
903
|
+
|
|
904
|
+
// Find by id field
|
|
905
|
+
const subtree1 = t.cloneSubtree(tree, { id: 2 })
|
|
906
|
+
console.log(subtree1)
|
|
907
|
+
// [{ id: 2, name: 'sub1', children: [{ id: 4, name: 'sub1-1' }] }]
|
|
908
|
+
|
|
909
|
+
// Find by name field
|
|
910
|
+
const subtree2 = t.cloneSubtree(tree, { name: 'sub1' })
|
|
911
|
+
console.log(subtree2)
|
|
912
|
+
// [{ id: 2, name: 'sub1', children: [{ id: 4, name: 'sub1-1' }] }]
|
|
913
|
+
|
|
914
|
+
// Find by other field (e.g., code)
|
|
915
|
+
const treeWithCode = [
|
|
916
|
+
{
|
|
917
|
+
id: 1,
|
|
918
|
+
code: 'A001',
|
|
919
|
+
children: [
|
|
920
|
+
{ id: 2, code: 'B001', children: [{ id: 4, code: 'C001' }] }
|
|
921
|
+
]
|
|
922
|
+
}
|
|
923
|
+
]
|
|
924
|
+
const subtree3 = t.cloneSubtree(treeWithCode, { code: 'B001' })
|
|
925
|
+
console.log(subtree3)
|
|
926
|
+
// [{ id: 2, code: 'B001', children: [{ id: 4, code: 'C001' }] }]
|
|
927
|
+
|
|
928
|
+
// Support custom children field name
|
|
929
|
+
const customTree = [
|
|
930
|
+
{ nodeId: 1, subNodes: [{ nodeId: 2 }] }
|
|
931
|
+
]
|
|
932
|
+
const subtree4 = t.cloneSubtree(customTree, { nodeId: 2 }, { children: 'subNodes', id: 'nodeId' })
|
|
933
|
+
console.log(subtree4)
|
|
934
|
+
// [{ nodeId: 2 }]
|
|
935
|
+
|
|
936
|
+
// Modifying the cloned subtree won't affect the original
|
|
937
|
+
subtree1[0].name = 'modified'
|
|
938
|
+
console.log(tree[0].children[0].name) // 'sub1'
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
**Parameters:**
|
|
942
|
+
- `tree`: Tree-structured data
|
|
943
|
+
- `target`: Target node object, e.g., `{ id: 1 }` or `{ name: 'sub1' }` or `{ code: 'B001' }`, object must contain only one field
|
|
944
|
+
- `fieldNames`: Custom field name configuration (optional, used to customize `children` field name, search field is determined by the key name in the `target` object)
|
|
945
|
+
|
|
946
|
+
**Notes:**
|
|
947
|
+
- Returns a subtree containing the target node (deep cloned)
|
|
948
|
+
- Returns an empty array if the target node is not found
|
|
949
|
+
- Recursively deep clones all child nodes
|
|
950
|
+
- Must pass an object, search field is determined by the object's key name (e.g., `{ id: 1 }` searches by `id` field, `{ name: 'xxx' }` searches by `name` field)
|
|
951
|
+
- `fieldNames` parameter is used to customize `children` field name, defining `id` has no effect
|
|
952
|
+
|
|
953
|
+
### cloneWithTransform
|
|
954
|
+
|
|
955
|
+
Clone tree-structured data and apply a transform function to each node. Suitable for modifying node data while cloning.
|
|
956
|
+
|
|
957
|
+
```javascript
|
|
958
|
+
const tree = [
|
|
959
|
+
{ id: 1, name: 'node1', children: [{ id: 2, name: 'node2' }] }
|
|
960
|
+
]
|
|
961
|
+
|
|
962
|
+
// Clone and add label field
|
|
963
|
+
const cloned = t.cloneWithTransform(tree, (node) => ({
|
|
964
|
+
...node,
|
|
965
|
+
label: node.name,
|
|
966
|
+
processed: true
|
|
967
|
+
}))
|
|
968
|
+
|
|
969
|
+
console.log(cloned[0].label) // 'node1'
|
|
970
|
+
console.log(cloned[0].processed) // true
|
|
971
|
+
console.log(cloned[0].children[0].label) // 'node2'
|
|
972
|
+
console.log(tree[0].label) // undefined (original tree not modified)
|
|
973
|
+
```
|
|
974
|
+
|
|
975
|
+
**Parameters:**
|
|
976
|
+
- `tree`: Tree-structured data
|
|
977
|
+
- `transform`: Transform function that receives a node and returns the transformed node
|
|
978
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
979
|
+
|
|
980
|
+
**Notes:**
|
|
981
|
+
- Recursively transforms all levels of nodes
|
|
982
|
+
- Returns the transformed tree (deep cloned), won't modify the original tree
|
|
983
|
+
- The transform function should return a new node object
|
|
984
|
+
|
|
985
|
+
---
|
|
986
|
+
|
|
987
|
+
## Relationship Query Methods
|
|
988
|
+
|
|
989
|
+
Methods for getting relationship information between nodes (parent-child relationships, sibling relationships, depth, etc.).
|
|
703
990
|
|
|
704
991
|
### getParentTree
|
|
705
992
|
|
|
@@ -850,7 +1137,9 @@ console.log(depth) // 2
|
|
|
850
1137
|
|
|
851
1138
|
---
|
|
852
1139
|
|
|
853
|
-
## Validation Methods
|
|
1140
|
+
## Data Validation Methods
|
|
1141
|
+
|
|
1142
|
+
Methods for validating the validity of tree-structured data and node types.
|
|
854
1143
|
|
|
855
1144
|
### isLeafNode
|
|
856
1145
|
|
|
@@ -902,6 +1191,8 @@ console.log(t.isLeafNode(customNode, fieldNames)) // true
|
|
|
902
1191
|
|
|
903
1192
|
Check if a node is a root node (has no parent). Root nodes are top-level nodes in the tree-structured data array.
|
|
904
1193
|
|
|
1194
|
+
**Performance Optimization**: Optimized to use a single traversal, avoiding duplicate tree traversals.
|
|
1195
|
+
|
|
905
1196
|
```javascript
|
|
906
1197
|
// Check root node
|
|
907
1198
|
const treeData = [
|
|
@@ -1249,6 +1540,435 @@ console.log(t.isSafeTreeDepth(customTree, 2, fieldNames)) // false
|
|
|
1249
1540
|
- Prevent recursion call stack overflow
|
|
1250
1541
|
- Performance optimization, avoid processing trees that are too deep
|
|
1251
1542
|
|
|
1543
|
+
---
|
|
1544
|
+
|
|
1545
|
+
## Aggregation Analysis Methods
|
|
1546
|
+
|
|
1547
|
+
Methods for aggregating, statistics, and analyzing tree-structured data.
|
|
1548
|
+
|
|
1549
|
+
### reduceTree
|
|
1550
|
+
|
|
1551
|
+
Reduce tree-structured data, traverses all nodes and accumulates results.
|
|
1552
|
+
|
|
1553
|
+
```javascript
|
|
1554
|
+
const tree = [
|
|
1555
|
+
{ id: 1, value: 10 },
|
|
1556
|
+
{ id: 2, value: 20, children: [{ id: 3, value: 30 }] }
|
|
1557
|
+
]
|
|
1558
|
+
|
|
1559
|
+
// Calculate the sum of all node values
|
|
1560
|
+
const sum = t.reduceTree(tree, (acc, node) => acc + (node.value || 0), 0)
|
|
1561
|
+
console.log(sum) // 60
|
|
1562
|
+
|
|
1563
|
+
// Collect all node IDs
|
|
1564
|
+
const ids = t.reduceTree(tree, (ids, node) => {
|
|
1565
|
+
ids.push(node.id)
|
|
1566
|
+
return ids
|
|
1567
|
+
}, [])
|
|
1568
|
+
console.log(ids) // [1, 2, 3]
|
|
1569
|
+
```
|
|
1570
|
+
|
|
1571
|
+
**Parameters:**
|
|
1572
|
+
- `tree`: Tree-structured data
|
|
1573
|
+
- `reducer`: Reduction function that receives accumulator and current node, returns new accumulator
|
|
1574
|
+
- `initialValue`: Initial value
|
|
1575
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1576
|
+
|
|
1577
|
+
**Notes:**
|
|
1578
|
+
- Traverses all nodes in depth-first order
|
|
1579
|
+
- Can be used to implement various aggregation operations
|
|
1580
|
+
|
|
1581
|
+
---
|
|
1582
|
+
|
|
1583
|
+
### aggregateTree
|
|
1584
|
+
|
|
1585
|
+
Aggregate tree-structured data by groups, supports multiple aggregation operations (sum, average, max, min, count).
|
|
1586
|
+
|
|
1587
|
+
```javascript
|
|
1588
|
+
const tree = [
|
|
1589
|
+
{ id: 1, category: 'A', value: 10, score: 80 },
|
|
1590
|
+
{ id: 2, category: 'A', value: 20, score: 90 },
|
|
1591
|
+
{ id: 3, category: 'B', value: 30, score: 70, children: [{ id: 4, category: 'B', value: 40, score: 85 }] }
|
|
1592
|
+
]
|
|
1593
|
+
|
|
1594
|
+
// Aggregate by category
|
|
1595
|
+
const result = t.aggregateTree(tree, {
|
|
1596
|
+
groupBy: node => node.category,
|
|
1597
|
+
aggregations: {
|
|
1598
|
+
totalValue: { operation: 'sum', field: 'value' },
|
|
1599
|
+
avgScore: { operation: 'avg', field: 'score' },
|
|
1600
|
+
maxValue: { operation: 'max', field: 'value' },
|
|
1601
|
+
count: { operation: 'count' }
|
|
1602
|
+
}
|
|
1603
|
+
})
|
|
1604
|
+
|
|
1605
|
+
console.log(result)
|
|
1606
|
+
// {
|
|
1607
|
+
// 'A': { totalValue: 30, avgScore: 85, maxValue: 20, count: 2 },
|
|
1608
|
+
// 'B': { totalValue: 70, avgScore: 77.5, maxValue: 40, count: 2 }
|
|
1609
|
+
// }
|
|
1610
|
+
```
|
|
1611
|
+
|
|
1612
|
+
**Parameters:**
|
|
1613
|
+
- `tree`: Tree-structured data
|
|
1614
|
+
- `options`: Aggregation options
|
|
1615
|
+
- `groupBy`: Grouping function that receives a node and returns a group key
|
|
1616
|
+
- `aggregations`: Aggregation configuration object, key is result field name, value is aggregation config
|
|
1617
|
+
- `operation`: Aggregation operation type ('sum' | 'avg' | 'max' | 'min' | 'count')
|
|
1618
|
+
- `field`: Field name to aggregate (not needed for count operation)
|
|
1619
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1620
|
+
|
|
1621
|
+
**Notes:**
|
|
1622
|
+
- Supports multiple aggregation operations simultaneously
|
|
1623
|
+
- Recursively processes all levels of nodes
|
|
1624
|
+
- Count operation counts node quantity, doesn't need field parameter
|
|
1625
|
+
|
|
1626
|
+
---
|
|
1627
|
+
|
|
1628
|
+
### groupTree
|
|
1629
|
+
|
|
1630
|
+
Group tree-structured data by field, returns node arrays grouped by field value.
|
|
1631
|
+
|
|
1632
|
+
```javascript
|
|
1633
|
+
const tree = [
|
|
1634
|
+
{ id: 1, category: 'A' },
|
|
1635
|
+
{ id: 2, category: 'A' },
|
|
1636
|
+
{ id: 3, category: 'B', children: [{ id: 4, category: 'B' }] }
|
|
1637
|
+
]
|
|
1638
|
+
|
|
1639
|
+
// Group by category field
|
|
1640
|
+
const grouped = t.groupTree(tree, 'category')
|
|
1641
|
+
console.log(grouped)
|
|
1642
|
+
// {
|
|
1643
|
+
// 'A': [{ id: 1, category: 'A' }, { id: 2, category: 'A' }],
|
|
1644
|
+
// 'B': [{ id: 3, category: 'B' }, { id: 4, category: 'B' }]
|
|
1645
|
+
// }
|
|
1646
|
+
```
|
|
1647
|
+
|
|
1648
|
+
**Parameters:**
|
|
1649
|
+
- `tree`: Tree-structured data
|
|
1650
|
+
- `field`: Grouping field name
|
|
1651
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1652
|
+
|
|
1653
|
+
**Notes:**
|
|
1654
|
+
- Returns references to original nodes, not deep copies
|
|
1655
|
+
- Recursively processes all levels of nodes
|
|
1656
|
+
|
|
1657
|
+
---
|
|
1658
|
+
|
|
1659
|
+
### groupByTree
|
|
1660
|
+
|
|
1661
|
+
Group tree-structured data by condition, uses custom function to determine group key.
|
|
1662
|
+
|
|
1663
|
+
```javascript
|
|
1664
|
+
const tree = [
|
|
1665
|
+
{ id: 1, value: 10 },
|
|
1666
|
+
{ id: 2, value: 20 },
|
|
1667
|
+
{ id: 3, value: 10, children: [{ id: 4, value: 30 }] }
|
|
1668
|
+
]
|
|
1669
|
+
|
|
1670
|
+
// Group by whether value is >= 20
|
|
1671
|
+
const grouped = t.groupByTree(tree, node => node.value >= 20 ? 'high' : 'low')
|
|
1672
|
+
console.log(grouped)
|
|
1673
|
+
// {
|
|
1674
|
+
// 'low': [{ id: 1, value: 10 }, { id: 3, value: 10 }],
|
|
1675
|
+
// 'high': [{ id: 2, value: 20 }, { id: 4, value: 30 }]
|
|
1676
|
+
// }
|
|
1677
|
+
```
|
|
1678
|
+
|
|
1679
|
+
**Parameters:**
|
|
1680
|
+
- `tree`: Tree-structured data
|
|
1681
|
+
- `groupFn`: Grouping function that receives a node and returns a group key
|
|
1682
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1683
|
+
|
|
1684
|
+
**Notes:**
|
|
1685
|
+
- Group keys are converted to strings
|
|
1686
|
+
- Returns references to original nodes, not deep copies
|
|
1687
|
+
|
|
1688
|
+
---
|
|
1689
|
+
|
|
1690
|
+
### sumTree
|
|
1691
|
+
|
|
1692
|
+
Calculate the sum of a field in tree-structured data.
|
|
1693
|
+
|
|
1694
|
+
```javascript
|
|
1695
|
+
const tree = [
|
|
1696
|
+
{ id: 1, value: 10 },
|
|
1697
|
+
{ id: 2, value: 20, children: [{ id: 3, value: 30 }] }
|
|
1698
|
+
]
|
|
1699
|
+
|
|
1700
|
+
// Calculate sum of value field
|
|
1701
|
+
const total = t.sumTree(tree, 'value')
|
|
1702
|
+
console.log(total) // 60
|
|
1703
|
+
```
|
|
1704
|
+
|
|
1705
|
+
**Parameters:**
|
|
1706
|
+
- `tree`: Tree-structured data
|
|
1707
|
+
- `field`: Field name
|
|
1708
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1709
|
+
|
|
1710
|
+
**Notes:**
|
|
1711
|
+
- Missing or null/undefined values are treated as 0
|
|
1712
|
+
- Recursively processes all levels of nodes
|
|
1713
|
+
|
|
1714
|
+
---
|
|
1715
|
+
|
|
1716
|
+
### avgTree
|
|
1717
|
+
|
|
1718
|
+
Calculate the average value of a field in tree-structured data.
|
|
1719
|
+
|
|
1720
|
+
```javascript
|
|
1721
|
+
const tree = [
|
|
1722
|
+
{ id: 1, value: 10 },
|
|
1723
|
+
{ id: 2, value: 20 },
|
|
1724
|
+
{ id: 3, value: 30 }
|
|
1725
|
+
]
|
|
1726
|
+
|
|
1727
|
+
// Calculate average of value field
|
|
1728
|
+
const average = t.avgTree(tree, 'value')
|
|
1729
|
+
console.log(average) // 20
|
|
1730
|
+
```
|
|
1731
|
+
|
|
1732
|
+
**Parameters:**
|
|
1733
|
+
- `tree`: Tree-structured data
|
|
1734
|
+
- `field`: Field name
|
|
1735
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1736
|
+
|
|
1737
|
+
**Notes:**
|
|
1738
|
+
- Ignores null and undefined values
|
|
1739
|
+
- Returns 0 if all values are null/undefined
|
|
1740
|
+
|
|
1741
|
+
---
|
|
1742
|
+
|
|
1743
|
+
### maxTree
|
|
1744
|
+
|
|
1745
|
+
Get the maximum value of a field in tree-structured data.
|
|
1746
|
+
|
|
1747
|
+
```javascript
|
|
1748
|
+
const tree = [
|
|
1749
|
+
{ id: 1, value: 10 },
|
|
1750
|
+
{ id: 2, value: 30 },
|
|
1751
|
+
{ id: 3, value: 20 }
|
|
1752
|
+
]
|
|
1753
|
+
|
|
1754
|
+
// Get maximum value of value field
|
|
1755
|
+
const max = t.maxTree(tree, 'value')
|
|
1756
|
+
console.log(max) // 30
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1759
|
+
**Parameters:**
|
|
1760
|
+
- `tree`: Tree-structured data
|
|
1761
|
+
- `field`: Field name
|
|
1762
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1763
|
+
|
|
1764
|
+
**Notes:**
|
|
1765
|
+
- Only processes numeric values
|
|
1766
|
+
- Returns null if tree is empty or has no valid values
|
|
1767
|
+
|
|
1768
|
+
---
|
|
1769
|
+
|
|
1770
|
+
### minTree
|
|
1771
|
+
|
|
1772
|
+
Get the minimum value of a field in tree-structured data.
|
|
1773
|
+
|
|
1774
|
+
```javascript
|
|
1775
|
+
const tree = [
|
|
1776
|
+
{ id: 1, value: 30 },
|
|
1777
|
+
{ id: 2, value: 10 },
|
|
1778
|
+
{ id: 3, value: 20 }
|
|
1779
|
+
]
|
|
1780
|
+
|
|
1781
|
+
// Get minimum value of value field
|
|
1782
|
+
const min = t.minTree(tree, 'value')
|
|
1783
|
+
console.log(min) // 10
|
|
1784
|
+
```
|
|
1785
|
+
|
|
1786
|
+
**Parameters:**
|
|
1787
|
+
- `tree`: Tree-structured data
|
|
1788
|
+
- `field`: Field name
|
|
1789
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1790
|
+
|
|
1791
|
+
**Notes:**
|
|
1792
|
+
- Only processes numeric values
|
|
1793
|
+
- Returns null if tree is empty or has no valid values
|
|
1794
|
+
|
|
1795
|
+
---
|
|
1796
|
+
|
|
1797
|
+
### countTree
|
|
1798
|
+
|
|
1799
|
+
Count the number of nodes in tree-structured data that meet a condition.
|
|
1800
|
+
|
|
1801
|
+
```javascript
|
|
1802
|
+
const tree = [
|
|
1803
|
+
{ id: 1, value: 10 },
|
|
1804
|
+
{ id: 2, value: 20 },
|
|
1805
|
+
{ id: 3, value: 10, children: [{ id: 4, value: 30 }] }
|
|
1806
|
+
]
|
|
1807
|
+
|
|
1808
|
+
// Count all nodes
|
|
1809
|
+
const total = t.countTree(tree)
|
|
1810
|
+
console.log(total) // 4
|
|
1811
|
+
|
|
1812
|
+
// Count nodes that meet condition
|
|
1813
|
+
const count = t.countTree(tree, node => node.value === 10)
|
|
1814
|
+
console.log(count) // 2
|
|
1815
|
+
```
|
|
1816
|
+
|
|
1817
|
+
**Parameters:**
|
|
1818
|
+
- `tree`: Tree-structured data
|
|
1819
|
+
- `conditionFn`: Condition function (optional), if not provided counts all nodes
|
|
1820
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1821
|
+
|
|
1822
|
+
**Notes:**
|
|
1823
|
+
- Counts all nodes if condition function is not provided
|
|
1824
|
+
- Recursively processes all levels of nodes
|
|
1825
|
+
|
|
1826
|
+
---
|
|
1827
|
+
|
|
1828
|
+
### getTreeStats
|
|
1829
|
+
|
|
1830
|
+
Get comprehensive statistics of tree-structured data.
|
|
1831
|
+
|
|
1832
|
+
```javascript
|
|
1833
|
+
const tree = [
|
|
1834
|
+
{ id: 1, children: [{ id: 2 }, { id: 3, children: [{ id: 4 }] }] }
|
|
1835
|
+
]
|
|
1836
|
+
|
|
1837
|
+
// Get statistics
|
|
1838
|
+
const stats = t.getTreeStats(tree)
|
|
1839
|
+
console.log(stats)
|
|
1840
|
+
// {
|
|
1841
|
+
// totalNodes: 4, // Total number of nodes
|
|
1842
|
+
// leafNodes: 2, // Number of leaf nodes
|
|
1843
|
+
// maxDepth: 3, // Maximum depth
|
|
1844
|
+
// minDepth: 1, // Minimum depth
|
|
1845
|
+
// avgDepth: 2, // Average depth
|
|
1846
|
+
// levels: 3 // Number of levels (equals maxDepth)
|
|
1847
|
+
// }
|
|
1848
|
+
```
|
|
1849
|
+
|
|
1850
|
+
**Parameters:**
|
|
1851
|
+
- `tree`: Tree-structured data
|
|
1852
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1853
|
+
|
|
1854
|
+
**Notes:**
|
|
1855
|
+
- Returns complete statistics object
|
|
1856
|
+
- Empty tree returns statistics with all values as 0
|
|
1857
|
+
|
|
1858
|
+
---
|
|
1859
|
+
|
|
1860
|
+
### analyzeTree
|
|
1861
|
+
|
|
1862
|
+
Comprehensively analyze tree-structured data, providing detailed statistics, distribution, balance analysis, and more.
|
|
1863
|
+
|
|
1864
|
+
```javascript
|
|
1865
|
+
const tree = [
|
|
1866
|
+
{ id: 1, children: [{ id: 2 }, { id: 3, children: [{ id: 4 }] }] }
|
|
1867
|
+
]
|
|
1868
|
+
|
|
1869
|
+
// Comprehensive tree structure analysis
|
|
1870
|
+
const analysis = t.analyzeTree(tree)
|
|
1871
|
+
console.log(analysis)
|
|
1872
|
+
// {
|
|
1873
|
+
// // Basic Statistics
|
|
1874
|
+
// totalNodes: 4, // Total number of nodes
|
|
1875
|
+
// leafNodes: 2, // Number of leaf nodes
|
|
1876
|
+
// internalNodes: 2, // Number of internal nodes
|
|
1877
|
+
// maxDepth: 3, // Maximum depth
|
|
1878
|
+
// minDepth: 1, // Minimum depth
|
|
1879
|
+
// avgDepth: 2, // Average depth
|
|
1880
|
+
// levels: 3, // Number of levels
|
|
1881
|
+
//
|
|
1882
|
+
// // Level Analysis
|
|
1883
|
+
// byLevel: { 0: 1, 1: 2, 2: 1 }, // Node count by level
|
|
1884
|
+
// maxWidth: 2, // Maximum width (max nodes in a single level)
|
|
1885
|
+
// avgWidth: 1.33, // Average width
|
|
1886
|
+
// widthByLevel: { 0: 1, 1: 2, 2: 1 }, // Width per level
|
|
1887
|
+
//
|
|
1888
|
+
// // Branching Factor Analysis
|
|
1889
|
+
// avgBranchingFactor: 1.5, // Average branching factor (avg children per node)
|
|
1890
|
+
// maxBranchingFactor: 2, // Maximum branching factor
|
|
1891
|
+
// minBranchingFactor: 1, // Minimum branching factor
|
|
1892
|
+
// branchingFactorDistribution: { 1: 1, 2: 1 }, // Branching factor distribution
|
|
1893
|
+
//
|
|
1894
|
+
// // Depth Distribution
|
|
1895
|
+
// depthDistribution: { 1: 1, 2: 2, 3: 1 }, // Node count by depth
|
|
1896
|
+
//
|
|
1897
|
+
// // Balance Analysis
|
|
1898
|
+
// depthVariance: 0.5, // Depth variance (smaller = more balanced)
|
|
1899
|
+
// isBalanced: true, // Whether tree is balanced
|
|
1900
|
+
// balanceRatio: 0.33, // Balance ratio (minDepth/maxDepth)
|
|
1901
|
+
//
|
|
1902
|
+
// // Path Analysis
|
|
1903
|
+
// avgPathLength: 2.25, // Average path length
|
|
1904
|
+
// maxPathLength: 3, // Maximum path length
|
|
1905
|
+
// minPathLength: 1, // Minimum path length
|
|
1906
|
+
//
|
|
1907
|
+
// // Leaf Node Analysis
|
|
1908
|
+
// leafNodeRatio: 0.5, // Leaf node ratio
|
|
1909
|
+
// leafNodesByLevel: { 2: 1, 3: 1 } // Leaf nodes per level
|
|
1910
|
+
// }
|
|
1911
|
+
```
|
|
1912
|
+
|
|
1913
|
+
**Parameters:**
|
|
1914
|
+
- `tree`: Tree-structured data
|
|
1915
|
+
- `options`: Analysis options (optional), can specify which statistics to calculate, defaults to calculating all statistics
|
|
1916
|
+
- `includeBasic`: Whether to include basic statistics (totalNodes, leafNodes, internalNodes, maxDepth, minDepth, avgDepth, levels), default `true`
|
|
1917
|
+
- `includeLevelAnalysis`: Whether to include level analysis (byLevel, maxWidth, avgWidth, widthByLevel), default `true`
|
|
1918
|
+
- `includeBranchingFactor`: Whether to include branching factor analysis (avgBranchingFactor, maxBranchingFactor, minBranchingFactor, branchingFactorDistribution), default `true`
|
|
1919
|
+
- `includeDepthDistribution`: Whether to include depth distribution (depthDistribution), default `true`
|
|
1920
|
+
- `includeBalanceAnalysis`: Whether to include balance analysis (depthVariance, isBalanced, balanceRatio), default `true`
|
|
1921
|
+
- `includePathAnalysis`: Whether to include path analysis (avgPathLength, maxPathLength, minPathLength), default `true`
|
|
1922
|
+
- `includeLeafAnalysis`: Whether to include leaf node analysis (leafNodeRatio, leafNodesByLevel), default `true`
|
|
1923
|
+
- `fieldNames`: Custom field name configuration (optional)
|
|
1924
|
+
|
|
1925
|
+
```javascript
|
|
1926
|
+
// Calculate only basic statistics and branching factor (performance optimization)
|
|
1927
|
+
const quickAnalysis = t.analyzeTree(tree, {
|
|
1928
|
+
includeBasic: true,
|
|
1929
|
+
includeBranchingFactor: true,
|
|
1930
|
+
includeLevelAnalysis: false,
|
|
1931
|
+
includeDepthDistribution: false,
|
|
1932
|
+
includeBalanceAnalysis: false,
|
|
1933
|
+
includePathAnalysis: false,
|
|
1934
|
+
includeLeafAnalysis: false,
|
|
1935
|
+
})
|
|
1936
|
+
console.log(quickAnalysis.totalNodes) // 4
|
|
1937
|
+
console.log(quickAnalysis.maxBranchingFactor) // 2
|
|
1938
|
+
console.log(quickAnalysis.byLevel) // {} (not calculated)
|
|
1939
|
+
|
|
1940
|
+
// Calculate only balance analysis
|
|
1941
|
+
const balanceAnalysis = t.analyzeTree(tree, {
|
|
1942
|
+
includeBasic: true,
|
|
1943
|
+
includeBalanceAnalysis: true,
|
|
1944
|
+
includeLevelAnalysis: false,
|
|
1945
|
+
includeBranchingFactor: false,
|
|
1946
|
+
includeDepthDistribution: false,
|
|
1947
|
+
includePathAnalysis: false,
|
|
1948
|
+
includeLeafAnalysis: false,
|
|
1949
|
+
})
|
|
1950
|
+
console.log(balanceAnalysis.isBalanced) // true/false
|
|
1951
|
+
console.log(balanceAnalysis.depthVariance) // 0.5
|
|
1952
|
+
```
|
|
1953
|
+
|
|
1954
|
+
**Analysis information includes:**
|
|
1955
|
+
|
|
1956
|
+
1. **Basic Statistics**: Total nodes, leaf nodes, internal nodes, depth information, etc.
|
|
1957
|
+
2. **Level Analysis**: Nodes per level, maximum width, average width, etc.
|
|
1958
|
+
3. **Branching Factor Analysis**: Average/max/min branching factor, branching factor distribution, etc.
|
|
1959
|
+
4. **Depth Distribution**: Number of nodes at each depth
|
|
1960
|
+
5. **Balance Analysis**: Depth variance, whether balanced, balance ratio, etc.
|
|
1961
|
+
6. **Path Analysis**: Average/max/min path length
|
|
1962
|
+
7. **Leaf Node Analysis**: Leaf node ratio, leaf nodes per level
|
|
1963
|
+
|
|
1964
|
+
**Notes:**
|
|
1965
|
+
- Provides comprehensive tree structure analysis, suitable for performance optimization, structure evaluation, etc.
|
|
1966
|
+
- `isBalanced` is determined based on depth variance and depth range. A tree is considered balanced if depth variance < 2 and depth range ≤ 2
|
|
1967
|
+
- `balanceRatio` closer to 1 indicates a more balanced tree
|
|
1968
|
+
- **Performance Optimization**: Use the `options` parameter to calculate only the needed statistics, which can significantly improve performance for large tree structures
|
|
1969
|
+
|
|
1970
|
+
---
|
|
1971
|
+
|
|
1252
1972
|
## Custom Field Names
|
|
1253
1973
|
|
|
1254
1974
|
All methods support custom property names for children and id through the last parameter, passing in a configuration object:
|
|
@@ -1269,16 +1989,16 @@ const foundNode2 = t.findTree(customTreeData, (node) => node.nodeId === 2, field
|
|
|
1269
1989
|
### Run Tests
|
|
1270
1990
|
|
|
1271
1991
|
```bash
|
|
1272
|
-
# Run all tests (automatically build then test source + bundled files,
|
|
1992
|
+
# Run all tests (automatically build then test source + bundled files, 712 test cases)
|
|
1273
1993
|
npm test
|
|
1274
1994
|
|
|
1275
1995
|
# Run all tests (once, don't watch for file changes)
|
|
1276
1996
|
npm test -- --run
|
|
1277
1997
|
|
|
1278
|
-
# Test source code only (
|
|
1998
|
+
# Test source code only (447 test cases)
|
|
1279
1999
|
npm run test:src
|
|
1280
2000
|
|
|
1281
|
-
# Test bundled files only (
|
|
2001
|
+
# Test bundled files only (447 test cases, requires npm run build first)
|
|
1282
2002
|
npm run test:dist
|
|
1283
2003
|
|
|
1284
2004
|
# Run tests and generate coverage report
|