tree-processor 0.10.0 → 0.11.1
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 +729 -36
- package/README.md +730 -38
- 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 +130 -55
- package/dist/tree-processor.esm.js +116 -41
- package/dist/tree-processor.umd.js +174 -99
- package/package.json +4 -2
package/README.en.md
CHANGED
|
@@ -9,12 +9,13 @@
|
|
|
9
9
|
<div align="center">
|
|
10
10
|
|
|
11
11
|

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

|
|
14
|
+

|
|
14
15
|

|
|
15
|
-

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