Skip to content

Commit 37ea2f9

Browse files
committed
feat: creating getSubMap and clone
Creating two methods to obtain submaps With different flavors
1 parent 839944e commit 37ea2f9

File tree

5 files changed

+393
-37
lines changed

5 files changed

+393
-37
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
2+
3+
4+
# Advanced Example: Methods to Obtain Subtrees in NestedMap
5+
6+
`NestedMap` provides two powerful methods for working with subtrees: `getSubMap` and `clone`.
7+
8+
- **`getSubMap`** creates a live, synchronized view into a subtree, allowing you to operate directly on a branch of the original map. Changes made through a submap are immediately reflected in the parent map, making it ideal for scoped operations, modular code, and UI components that need to interact with a specific branch.
9+
10+
- **`clone`** creates a deep, independent copy of the entire map or a subtree. The cloned map is a snapshot: changes to the clone do not affect the original, and vice versa. This is useful for backups, branching, experimentation, or any scenario where you need a safe copy of your data structure.
11+
> **Note:** The `clone` method copies the tree structure and all keys, but does not deep clone the values themselves. If your values are objects or arrays, both the original and the clone will reference the same value objects. For true deep value cloning, you must clone values manually or use a deep clone utility.
12+
13+
Both methods enable focused manipulation of nested data, but with different synchronization and independence properties. The following sections explain their usage, differences, and practical scenarios for each.
14+
15+
16+
## What is `getSubMap`?
17+
`getSubMap(basePath)` returns a new `NestedMap` instance that operates on the subtree rooted at `basePath`. All changes (set, delete) made through the submap are reflected in the original map, and vice versa. Traversal from the submap yields keys relative to the base path.
18+
19+
20+
## What is `clone`?
21+
The `clone` method creates a deep copy of the entire map or a subtree (if a base path is provided). The cloned map is completely independent: changes to the clone do not affect the original, and vice versa. Traversal from the clone yields keys in the same order as the original.
22+
23+
## Example Usage
24+
25+
```typescript
26+
import { NestedMap } from 'js-tuple';
27+
28+
const map = new NestedMap<number[], string>();
29+
map.set([1, 2, 3], 'a');
30+
map.set([1, 2, 4], 'b');
31+
map.set([1, 2, 5], 'c');
32+
map.set([1, 9, 9], 'd');
33+
34+
// Create a submap rooted at [1, 2]
35+
const subMap = map.getSubMap([1, 2]);
36+
37+
// Traversal yields relative keys:
38+
for (const [key, value] of subMap.entries()) {
39+
// key: [3], [4], [5]
40+
// value: 'a', 'b', 'c'
41+
}
42+
43+
// Setting via subMap updates the original map
44+
subMap.set([6], 'e');
45+
console.log(map.get([1, 2, 6])); // 'e'
46+
47+
// Deleting via subMap updates the original map
48+
subMap.delete([3]);
49+
console.log(map.has([1, 2, 3])); // false
50+
51+
52+
// Traversal in subMap is scoped to its subtree
53+
console.log([...subMap.entries()]); // [ [ [4], 'b' ], [ [5], 'c' ], [ [6], 'e' ] ]
54+
55+
// Clone the entire map
56+
const clone = map.clone();
57+
console.log([...clone.entries()]); // [ [ [1, 2, 4], 'b' ], [ [1, 2, 5], 'c' ], ... ]
58+
59+
// Clone a subtree
60+
const subClone = map.clone([1, 2]);
61+
console.log([...subClone.entries()]); // [ [ [3], 'a' ], [ [4], 'b' ], [ [5], 'c' ] ]
62+
63+
// Changes to clone do not affect the original
64+
subClone.set([3], 'z');
65+
console.log(map.get([1, 2, 3])); // 'a'
66+
console.log(subClone.get([3])); // 'z'
67+
```
68+
69+
70+
## When to Use `getSubMap` vs. `clone`
71+
72+
| Feature | getSubMap | clone |
73+
|------------------------|--------------------------------|-------------------------------|
74+
| Synchronization | Changes affect original | Changes are independent |
75+
| Traversal keys | Relative to base path | Relative to base path |
76+
| Use case | Scoped, live view | Snapshot, backup, branching |
77+
| Memory usage | Lightweight (view) | Full copy (higher memory) |
78+
| Bulk operations | Directly on original | On a copy |
79+
80+
**Use `getSubMap` when:**
81+
- You want a live, synchronized view into a subtree.
82+
- You need to update or traverse a branch and reflect changes in the original map.
83+
- You want to pass a scoped view to a function or component.
84+
- You'll not update the tree (as clone will use more memory).
85+
86+
**Use `clone` when:**
87+
- You need a snapshot or backup of the map or a subtree.
88+
- You want to branch, experiment, or perform bulk operations without affecting the original.
89+
- You need to serialize, persist, or transfer a copy of the data.
90+
91+
- **Scoped Operations:**
92+
- When you want to work with a specific branch of a large nested map without affecting or traversing unrelated branches.
93+
- **Modular Code:**
94+
- Pass submaps to functions or modules that only need access to a subtree, improving encapsulation and reducing complexity.
95+
- **Efficient Bulk Updates:**
96+
- Apply bulk changes, deletions, or traversals to a subtree without manually handling the full key paths.
97+
- **UI/UX Scenarios:**
98+
- In tree-based UIs, bind a submap to a component representing a subtree, allowing local edits and traversal.
99+
- **Multi-tenant Data:**
100+
- Partition data by tenant/user/project, and operate on each partition via submaps for isolation and clarity.
101+
102+
103+
104+
## Notes
105+
- Traversal from a submap yields keys relative to the base path.
106+
- Traversal from a clone yields keys in the same order as the original.
107+
- All changes in submaps are synchronized with the original map.
108+
- Clones are independent and do not affect the original.
109+
- Submaps are lightweight views, not copies.
110+
- Clones are full copies and use more memory.
111+
- **Clone copies the tree structure and keys, but does not deep clone values.** If your values are objects, both maps will reference the same objects unless you clone them separately.
112+
113+
---
114+
For more advanced usage, see other examples in this documentation.

libs/js-tuple/src/internal/queue.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ export class Queue<T> {
5151
return item;
5252
}
5353

54+
exhaust(cb: (item: T) => void): void {
55+
while (this.length) {
56+
const item = this.pop() as T;
57+
cb(item);
58+
}
59+
}
60+
5461
get length(): number {
5562
return this._length;
5663
}

0 commit comments

Comments
 (0)