Basic tree traversal functions
MIT License
@suchipi/traverse
Basic traverse function for deeply iterating over objects/arrays/etc.
import { traverse } from "@suchipi/traverse";
// It can traverse any JSON-compatible structure.
const tree = {
type: "Root",
left: {
type: "Left",
children: [1, 2, 3],
},
right: {
type: "Right",
children: [4, 5, 6],
},
};
traverse(tree, {
// If you provide an `after` callback, it will be called on the way *up*
// the traversal stack; this is equivalent to a depth-first search.
after: (value, path) => {
console.log(`At '.${path.join(".")}':`, value);
},
});
// Output:
//
// At '.type': 'Root'
// At '.left.type': 'Left'
// At '.left.children.0': 1
// At '.left.children.1': 2
// At '.left.children.2': 3
// At '.left.children': [ 1, 2, 3 ]
// At '.left': { type: 'Left', children: [ 1, 2, 3 ] }
// At '.right.type': 'Right'
// At '.right.children.0': 4
// At '.right.children.1': 5
// At '.right.children.2': 6
// At '.right.children': [ 4, 5, 6 ]
// At '.right': { type: 'Right', children: [ 4, 5, 6 ] }
// At '.': {
// type: 'Root',
// left: { type: 'Left', children: [ 1, 2, 3 ] },
// right: { type: 'Right', children: [ 4, 5, 6 ] }
// }
traverse(tree, {
// If you provide a `before` callback, it will be called on the way *down*
// the traversal stack; this is equivalent to a breadth-first search.
before: (value, path) => {
console.log(`At '.${path.join(".")}':`, value);
},
});
// Output:
//
// At '.': {
// type: 'Root',
// left: { type: 'Left', children: [ 1, 2, 3 ] },
// right: { type: 'Right', children: [ 4, 5, 6 ] }
// }
// At '.type': Root
// At '.left': { type: 'Left', children: [ 1, 2, 3 ] }
// At '.left.type': Left
// At '.left.children': [ 1, 2, 3 ]
// At '.left.children.0': 1
// At '.left.children.1': 2
// At '.left.children.2': 3
// At '.right': { type: 'Right', children: [ 4, 5, 6 ] }
// At '.right.type': Right
// At '.right.children': [ 4, 5, 6 ]
// At '.right.children.0': 4
// At '.right.children.1': 5
// At '.right.children.2': 6
This module has two named exports:
traverse
stop
traverse
The traverse
function has the following type signature:
function traverse(
tree: any,
callbacks?: {
before?: (value: any, path: Array<string | number>) => void | typeof stop;
after?: (value: any, path: Array<string | number>) => void;
},
): void;
Pass in any JSON-compatible value (the tree
parameter) and a callback function (the callback
parameter). Your tree
will be searched through, and callback
will be called for each descendant in the tree.
When callback
is called, it will be called with two arguments:
tree
object to this descendant (an array of strings or numbers)stop
You can return stop
from a before
callback passed into traverse
to stop traversing downwards beyond the current object's children.
The path
Array your callback receives is suitable for use in lodash's set
and get
functions. As such, you can use lodash's set
function to mutate a tree while you traverse over it.
If you want to create a new tree instead of mutating the existing one, you can combine lodash's set
function with immer.
Don't pass an object with circular references into traverse
. If you do, a callstack overflow error will occur. To verify that the object you're passing into traverse
doesn't contain any circular references, you can try passing it into JSON.stringify
; JSON.stringify
will throw an error if you pass it an object with circular references.
If you're expecting an object property to be visited by traverse
, but it isn't, make sure the property is an "own," "enumerable" property. For instance, class methods found on an instance of a class are not "own" properties, so traverse
won't visit them. See MDN's article on 'Enumerability and ownership of properties' for more info.
The contents of Map
and Set
objects won't be visited by traverse
, because it's only designed with JSON-compatible values in mind. However, the Map
/Set
itself will be visited. As such, if you want to inspect the contents of a Map
/Set
, you can do so from within your callback. Alternatively, you can convert Map
s/Set
s in your tree into Objects or Arrays prior to passing your tree into traverse
.
MIT