or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

array-conversion.mdindex.mdtree-analysis.mdtree-construction.mdtree-iterators.mdtree-modification.mdtree-navigation.mdtree-traversal.md

tree-iterators.mddocs/

0

# Tree Iterators

1

2

ES6-compatible iterators for all traversal patterns with efficient lazy evaluation.

3

4

## Capabilities

5

6

### Children Iterator

7

8

Iterate over all children of a parent object.

9

10

```javascript { .api }

11

/**

12

* Iterate over all children of the given parent object

13

* Time Complexity: O(1) for a single iteration

14

* @param {Object} parent - Parent object

15

* @param {Object} [options] - Iterator options

16

* @param {boolean} [options.reverse=false] - Iterate in reverse order

17

* @returns {Iterator<Object>} ES6 iterator over children

18

*/

19

childrenIterator(parent: Object, options?: { reverse?: boolean }): Iterator<Object>;

20

```

21

22

### Previous Siblings Iterator

23

24

Iterate over all previous siblings of an object (in reverse tree order).

25

26

```javascript { .api }

27

/**

28

* Iterate over all previous siblings of the given object

29

* Time Complexity: O(1) for a single iteration

30

* @param {Object} object - Reference object

31

* @returns {Iterator<Object>} ES6 iterator over previous siblings

32

*/

33

previousSiblingsIterator(object: Object): Iterator<Object>;

34

```

35

36

### Next Siblings Iterator

37

38

Iterate over all next siblings of an object (in tree order).

39

40

```javascript { .api }

41

/**

42

* Iterate over all next siblings of the given object

43

* Time Complexity: O(1) for a single iteration

44

* @param {Object} object - Reference object

45

* @returns {Iterator<Object>} ES6 iterator over next siblings

46

*/

47

nextSiblingsIterator(object: Object): Iterator<Object>;

48

```

49

50

### Ancestors Iterator

51

52

Iterate over all inclusive ancestors of an object.

53

54

```javascript { .api }

55

/**

56

* Iterate over all inclusive ancestors of the given object

57

* Time Complexity: O(1) for a single iteration

58

* @param {Object} object - Starting object

59

* @returns {Iterator<Object>} ES6 iterator over ancestors (including the object itself)

60

*/

61

ancestorsIterator(object: Object): Iterator<Object>;

62

```

63

64

### Tree Iterator

65

66

Iterate over all descendants of an object (in tree order).

67

68

```javascript { .api }

69

/**

70

* Iterate over all descendants of the given object in tree order

71

* Time Complexity: O(n) worst case for single iteration, O(n) amortized when completing

72

* @param {Object} root - Root object of tree/subtree

73

* @param {Object} [options] - Iterator options

74

* @param {boolean} [options.reverse=false] - Iterate in reverse tree order

75

* @returns {Iterator<Object>} ES6 iterator over tree descendants

76

*/

77

treeIterator(root: Object, options?: { reverse?: boolean }): Iterator<Object>;

78

```

79

80

## Iterator Protocol

81

82

All iterators implement the ES6 iterator protocol and are compatible with:

83

84

```javascript { .api }

85

// Iterator interface

86

interface Iterator<T> {

87

next(): IteratorResult<T>;

88

[Symbol.iterator](): Iterator<T>;

89

}

90

91

interface IteratorResult<T> {

92

done: boolean;

93

value: T;

94

}

95

```

96

97

## Usage Examples

98

99

### Basic Iterator Usage

100

101

```javascript

102

const SymbolTree = require("symbol-tree");

103

const tree = new SymbolTree();

104

105

// Build a tree structure

106

const parent = { name: "parent" };

107

const child1 = { name: "child1" };

108

const child2 = { name: "child2" };

109

const child3 = { name: "child3" };

110

111

tree.appendChild(parent, child1);

112

tree.appendChild(parent, child2);

113

tree.appendChild(parent, child3);

114

115

// Iterate over children using for...of

116

for (const child of tree.childrenIterator(parent)) {

117

console.log(child.name);

118

}

119

// Output: child1, child2, child3

120

121

// Iterate in reverse

122

for (const child of tree.childrenIterator(parent, { reverse: true })) {

123

console.log(child.name);

124

}

125

// Output: child3, child2, child1

126

```

127

128

### Manual Iterator Control

129

130

```javascript

131

// Manual iterator control

132

const childIterator = tree.childrenIterator(parent);

133

134

let result = childIterator.next();

135

while (!result.done) {

136

console.log("Child:", result.value.name);

137

result = childIterator.next();

138

}

139

140

// Or using the iterator protocol

141

const children = [...tree.childrenIterator(parent)];

142

console.log(children.map(c => c.name)); // ["child1", "child2", "child3"]

143

```

144

145

### Sibling Iteration

146

147

```javascript

148

// Iterate over next siblings

149

for (const sibling of tree.nextSiblingsIterator(child1)) {

150

console.log("Next sibling:", sibling.name);

151

}

152

// Output: Next sibling: child2, Next sibling: child3

153

154

// Iterate over previous siblings

155

for (const sibling of tree.previousSiblingsIterator(child3)) {

156

console.log("Previous sibling:", sibling.name);

157

}

158

// Output: Previous sibling: child2, Previous sibling: child1

159

```

160

161

### Tree Structure Iteration

162

163

```javascript

164

// Build larger tree

165

const grandchild1 = { name: "grandchild1" };

166

const grandchild2 = { name: "grandchild2" };

167

tree.appendChild(child1, grandchild1);

168

tree.appendChild(child2, grandchild2);

169

170

// Iterate over entire tree

171

console.log("Forward tree iteration:");

172

for (const node of tree.treeIterator(parent, { reverse: false })) {

173

console.log(node.name);

174

}

175

// Output: parent, child1, grandchild1, child2, grandchild2, child3

176

177

console.log("Reverse tree iteration:");

178

for (const node of tree.treeIterator(parent, { reverse: true })) {

179

console.log(node.name);

180

}

181

// Output: child3, grandchild2, child2, grandchild1, child1, parent

182

```

183

184

### Ancestor Iteration

185

186

```javascript

187

// Iterate up the ancestor chain

188

console.log("Ancestors of grandchild1:");

189

for (const ancestor of tree.ancestorsIterator(grandchild1)) {

190

console.log(ancestor.name);

191

}

192

// Output: grandchild1, child1, parent

193

```

194

195

### Advanced Iterator Patterns

196

197

```javascript

198

// Find first child matching condition

199

function findChild(parent, predicate) {

200

for (const child of tree.childrenIterator(parent)) {

201

if (predicate(child)) {

202

return child;

203

}

204

}

205

return null;

206

}

207

208

const firstChildWithName = findChild(parent, child =>

209

child.name.includes("2")

210

);

211

console.log(firstChildWithName?.name); // "child2"

212

213

// Collect nodes at specific depth

214

function getNodesAtDepth(root, targetDepth) {

215

const nodes = [];

216

217

for (const node of tree.treeIterator(root)) {

218

const ancestors = [...tree.ancestorsIterator(node)];

219

const depth = ancestors.length - 1;

220

221

if (depth === targetDepth) {

222

nodes.push(node);

223

}

224

}

225

226

return nodes;

227

}

228

229

const depthOneNodes = getNodesAtDepth(parent, 1);

230

console.log(depthOneNodes.map(n => n.name)); // ["child1", "child2", "child3"]

231

```

232

233

### Functional Programming with Iterators

234

235

```javascript

236

// Convert iterators to arrays for functional operations

237

const childNames = [...tree.childrenIterator(parent)]

238

.map(child => child.name)

239

.filter(name => name.includes("child"))

240

.sort();

241

242

console.log(childNames); // ["child1", "child2", "child3"]

243

244

// Reduce over tree

245

const treeStats = [...tree.treeIterator(parent)]

246

.reduce((stats, node) => {

247

stats.total++;

248

if (tree.hasChildren(node)) {

249

stats.containers++;

250

} else {

251

stats.leaves++;

252

}

253

return stats;

254

}, { total: 0, containers: 0, leaves: 0 });

255

256

console.log(treeStats); // { total: 6, containers: 3, leaves: 3 }

257

```

258

259

### Performance-Conscious Patterns

260

261

```javascript

262

// Early termination (more efficient than converting to array first)

263

function findFirstLeafNode(root) {

264

for (const node of tree.treeIterator(root)) {

265

if (!tree.hasChildren(node)) {

266

return node; // Stop immediately when found

267

}

268

}

269

return null;

270

}

271

272

// Process in chunks to avoid memory pressure

273

function processTreeInChunks(root, chunkSize = 100) {

274

let chunk = [];

275

276

for (const node of tree.treeIterator(root)) {

277

chunk.push(node);

278

279

if (chunk.length >= chunkSize) {

280

processChunk(chunk);

281

chunk = []; // Clear for next chunk

282

}

283

}

284

285

// Process remaining items

286

if (chunk.length > 0) {

287

processChunk(chunk);

288

}

289

}

290

291

function processChunk(nodes) {

292

// Do something with the chunk of nodes

293

console.log(`Processing chunk of ${nodes.length} nodes`);

294

}

295

```

296

297

### Iterator Composition

298

299

```javascript

300

// Combine multiple iterators

301

function* getAllSiblings(node) {

302

// Yield previous siblings in reverse order

303

const prevSiblings = [...tree.previousSiblingsIterator(node)].reverse();

304

for (const sibling of prevSiblings) {

305

yield sibling;

306

}

307

308

// Yield the node itself

309

yield node;

310

311

// Yield next siblings

312

for (const sibling of tree.nextSiblingsIterator(node)) {

313

yield sibling;

314

}

315

}

316

317

// Usage

318

console.log("All siblings of child2:");

319

for (const sibling of getAllSiblings(child2)) {

320

console.log(sibling.name);

321

}

322

// Output: child1, child2, child3

323

324

// Create custom tree walker

325

function* walkTreeWithCallback(root, callback) {

326

for (const node of tree.treeIterator(root)) {

327

const result = callback(node);

328

if (result) {

329

yield { node, result };

330

}

331

}

332

}

333

334

// Usage

335

const results = [...walkTreeWithCallback(parent, node => {

336

if (node.name.includes("child")) {

337

return `Found child: ${node.name}`;

338

}

339

})];

340

341

console.log(results);

342

```

343

344

### DOM-Style Iterator Usage

345

346

```javascript

347

// Simulate DOM traversal patterns

348

function* getElementsOfType(root, tagName) {

349

for (const node of tree.treeIterator(root)) {

350

if (node.tagName === tagName) {

351

yield node;

352

}

353

}

354

}

355

356

function getParentElements(node) {

357

const parents = [];

358

359

for (const ancestor of tree.ancestorsIterator(node)) {

360

if (ancestor !== node && ancestor.nodeType === "element") {

361

parents.push(ancestor);

362

}

363

}

364

365

return parents;

366

}

367

368

// Find next element sibling

369

function getNextElementSibling(node) {

370

for (const sibling of tree.nextSiblingsIterator(node)) {

371

if (sibling.nodeType === "element") {

372

return sibling;

373

}

374

}

375

return null;

376

}

377

```