or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

import-export.mdindex.mdnode-construction.mdpath-resolution.mdsearch.mdtree-iteration.mdtree-rendering.mdutilities.md

tree-iteration.mddocs/

0

# Tree Traversal and Iteration

1

2

Multiple iteration strategies for traversing tree structures. This module provides different traversal algorithms with filtering and depth control options for comprehensive tree navigation.

3

4

## Capabilities

5

6

### PreOrderIter - Pre-order Traversal

7

8

Iterates over tree using pre-order strategy: visits node first, then its children. This is depth-first traversal where parent nodes are processed before their children.

9

10

```python { .api }

11

class PreOrderIter(AbstractIter):

12

"""

13

Pre-order tree iteration (node, then children).

14

15

Args:

16

node: Starting node for iteration

17

filter_: Function called with every node as argument, node is returned if True

18

stop: Stop iteration at node if stop function returns True for node

19

maxlevel: Maximum descending in the node hierarchy

20

"""

21

def __init__(self, node, filter_=None, stop=None, maxlevel=None): ...

22

```

23

24

**Usage Example:**

25

26

```python

27

from anytree import Node, PreOrderIter

28

29

root = Node("root")

30

sub0 = Node("sub0", parent=root)

31

sub0sub0 = Node("sub0sub0", parent=sub0)

32

sub0sub1 = Node("sub0sub1", parent=sub0)

33

sub1 = Node("sub1", parent=root)

34

35

# Basic pre-order iteration

36

for node in PreOrderIter(root):

37

print(node.name)

38

# Output: root, sub0, sub0sub0, sub0sub1, sub1

39

40

# With filter

41

for node in PreOrderIter(root, filter_=lambda n: "sub0" in n.name):

42

print(node.name)

43

# Output: sub0, sub0sub0, sub0sub1

44

45

# With max level

46

for node in PreOrderIter(root, maxlevel=2):

47

print(f"{' ' * node.depth}{node.name}")

48

```

49

50

### PostOrderIter - Post-order Traversal

51

52

Iterates over tree using post-order strategy: visits children first, then the node. Useful for operations that need to process children before parents (like deletion, size calculation).

53

54

```python { .api }

55

class PostOrderIter(AbstractIter):

56

"""

57

Post-order tree iteration (children, then node).

58

59

Args:

60

node: Starting node for iteration

61

filter_: Function called with every node as argument, node is returned if True

62

stop: Stop iteration at node if stop function returns True for node

63

maxlevel: Maximum descending in the node hierarchy

64

"""

65

def __init__(self, node, filter_=None, stop=None, maxlevel=None): ...

66

```

67

68

**Usage Example:**

69

70

```python

71

from anytree import Node, PostOrderIter

72

73

root = Node("root")

74

sub0 = Node("sub0", parent=root)

75

sub0sub0 = Node("sub0sub0", parent=sub0)

76

sub0sub1 = Node("sub0sub1", parent=sub0)

77

sub1 = Node("sub1", parent=root)

78

79

# Post-order iteration - children before parents

80

for node in PostOrderIter(root):

81

print(node.name)

82

# Output: sub0sub0, sub0sub1, sub0, sub1, root

83

84

# Calculate subtree sizes using post-order

85

def calculate_sizes(node):

86

for n in PostOrderIter(node):

87

n.size = 1 + sum(child.size for child in n.children)

88

return node.size

89

90

size = calculate_sizes(root)

91

print(f"Total nodes: {size}")

92

```

93

94

### LevelOrderIter - Level-order Traversal

95

96

Iterates over tree using level-order (breadth-first) strategy: visits all nodes at depth N before visiting nodes at depth N+1.

97

98

```python { .api }

99

class LevelOrderIter(AbstractIter):

100

"""

101

Level-order tree iteration (breadth-first).

102

103

Args:

104

node: Starting node for iteration

105

filter_: Function called with every node as argument, node is returned if True

106

stop: Stop iteration at node if stop function returns True for node

107

maxlevel: Maximum descending in the node hierarchy

108

"""

109

def __init__(self, node, filter_=None, stop=None, maxlevel=None): ...

110

```

111

112

**Usage Example:**

113

114

```python

115

from anytree import Node, LevelOrderIter

116

117

root = Node("root")

118

sub0 = Node("sub0", parent=root)

119

sub1 = Node("sub1", parent=root)

120

sub0sub0 = Node("sub0sub0", parent=sub0)

121

sub0sub1 = Node("sub0sub1", parent=sub0)

122

sub1sub0 = Node("sub1sub0", parent=sub1)

123

124

# Level-order iteration - breadth-first

125

for node in LevelOrderIter(root):

126

print(f"Level {node.depth}: {node.name}")

127

# Output:

128

# Level 0: root

129

# Level 1: sub0

130

# Level 1: sub1

131

# Level 2: sub0sub0

132

# Level 2: sub0sub1

133

# Level 2: sub1sub0

134

```

135

136

### LevelOrderGroupIter - Grouped Level-order

137

138

Iterates over tree using level-order strategy but returns groups of nodes for each level. Each iteration yields a tuple of all nodes at the current depth.

139

140

```python { .api }

141

class LevelOrderGroupIter(AbstractIter):

142

"""

143

Level-order tree iteration returning groups for each level.

144

145

Args:

146

node: Starting node for iteration

147

filter_: Function called with every node as argument, node is returned if True

148

stop: Stop iteration at node if stop function returns True for node

149

maxlevel: Maximum descending in the node hierarchy

150

"""

151

def __init__(self, node, filter_=None, stop=None, maxlevel=None): ...

152

```

153

154

**Usage Example:**

155

156

```python

157

from anytree import Node, LevelOrderGroupIter

158

159

root = Node("root")

160

sub0 = Node("sub0", parent=root)

161

sub1 = Node("sub1", parent=root)

162

sub0sub0 = Node("sub0sub0", parent=sub0)

163

sub0sub1 = Node("sub0sub1", parent=sub0)

164

165

# Group iteration - one tuple per level

166

for level_nodes in LevelOrderGroupIter(root):

167

names = [node.name for node in level_nodes]

168

print(f"Level: {names}")

169

# Output:

170

# Level: ['root']

171

# Level: ['sub0', 'sub1']

172

# Level: ['sub0sub0', 'sub0sub1']

173

174

# Useful for level-based processing

175

for depth, level_nodes in enumerate(LevelOrderGroupIter(root)):

176

print(f"Processing {len(level_nodes)} nodes at depth {depth}")

177

```

178

179

### ZigZagGroupIter - ZigZag Level-order

180

181

Iterates over tree using level-order strategy with alternating left-to-right and right-to-left direction for each level. Returns groups like LevelOrderGroupIter but alternates direction.

182

183

```python { .api }

184

class ZigZagGroupIter(AbstractIter):

185

"""

186

ZigZag level-order iteration returning groups (alternating direction).

187

188

Args:

189

node: Starting node for iteration

190

filter_: Function called with every node as argument, node is returned if True

191

stop: Stop iteration at node if stop function returns True for node

192

maxlevel: Maximum descending in the node hierarchy

193

"""

194

def __init__(self, node, filter_=None, stop=None, maxlevel=None): ...

195

```

196

197

**Usage Example:**

198

199

```python

200

from anytree import Node, ZigZagGroupIter

201

202

root = Node("root")

203

sub0 = Node("sub0", parent=root)

204

sub1 = Node("sub1", parent=root)

205

sub2 = Node("sub2", parent=root)

206

sub0sub0 = Node("sub0sub0", parent=sub0)

207

sub0sub1 = Node("sub0sub1", parent=sub0)

208

sub1sub0 = Node("sub1sub0", parent=sub1)

209

210

# ZigZag iteration - alternating direction per level

211

for level_nodes in ZigZagGroupIter(root):

212

names = [node.name for node in level_nodes]

213

print(f"Level: {names}")

214

# Output:

215

# Level: ['root']

216

# Level: ['sub0', 'sub1', 'sub2'] (left-to-right)

217

# Level: ['sub1sub0', 'sub0sub1', 'sub0sub0'] (right-to-left)

218

```

219

220

### AbstractIter - Base Iterator Class

221

222

Base class for all tree iterators. Provides common functionality and interface for custom iteration strategies.

223

224

```python { .api }

225

class AbstractIter:

226

"""

227

Base class for tree iteration.

228

"""

229

def __init__(self, node, filter_=None, stop=None, maxlevel=None): ...

230

231

def __iter__(self): ...

232

def __next__(self): ...

233

```

234

235

## Common Filtering Patterns

236

237

### Filter Functions

238

239

All iterators support filter functions for selective traversal:

240

241

```python

242

from anytree import Node, PreOrderIter

243

244

root = Node("root")

245

Node("file.txt", parent=root, type="file")

246

Node("doc.pdf", parent=root, type="file")

247

Node("subdir", parent=root, type="directory")

248

249

# Filter by attribute

250

files_only = PreOrderIter(root, filter_=lambda n: getattr(n, 'type', None) == 'file')

251

for node in files_only:

252

print(node.name)

253

254

# Filter by name pattern

255

txt_files = PreOrderIter(root, filter_=lambda n: n.name.endswith('.txt'))

256

for node in txt_files:

257

print(node.name)

258

259

# Filter by depth

260

shallow_nodes = PreOrderIter(root, filter_=lambda n: n.depth <= 2)

261

```

262

263

### Stop Functions

264

265

Control iteration termination with stop functions:

266

267

```python

268

from anytree import Node, PreOrderIter

269

270

root = Node("root")

271

private_dir = Node("private", parent=root)

272

Node("secret.txt", parent=private_dir)

273

public_dir = Node("public", parent=root)

274

Node("readme.txt", parent=public_dir)

275

276

# Stop at private directories

277

public_only = PreOrderIter(root, stop=lambda n: n.name == 'private')

278

for node in public_only:

279

print(node.name)

280

# Output: root, public, readme.txt (skips private subtree)

281

282

# Stop when reaching max file count

283

file_count = 0

284

def stop_at_limit(node):

285

global file_count

286

if hasattr(node, 'type') and node.type == 'file':

287

file_count += 1

288

return file_count >= 3

289

290

limited_iter = PreOrderIter(root, stop=stop_at_limit)

291

```

292

293

### Level Limits

294

295

Control maximum traversal depth:

296

297

```python

298

from anytree import Node, PreOrderIter

299

300

# Create deep tree

301

root = Node("level0")

302

current = root

303

for i in range(1, 6):

304

current = Node(f"level{i}", parent=current)

305

306

# Limit to first 3 levels

307

for node in PreOrderIter(root, maxlevel=3):

308

print(f"{' ' * node.depth}{node.name}")

309

# Output includes level0, level1, level2 only

310

```

311

312

## Performance Considerations

313

314

### Iterator Choice Guidelines

315

316

- **PreOrderIter**: Best for depth-first processing, tree serialization

317

- **PostOrderIter**: Best for bottom-up calculations, tree deletion

318

- **LevelOrderIter**: Best for breadth-first analysis, finding shortest paths

319

- **LevelOrderGroupIter**: Best for level-based batch processing

320

- **ZigZagGroupIter**: Best for balanced tree processing, visualization

321

322

### Memory Usage

323

324

All iterators are lazy and memory-efficient, yielding nodes on-demand rather than creating lists. For very large trees, prefer iterators over collecting results into lists:

325

326

```python

327

# Memory efficient - processes one node at a time

328

for node in PreOrderIter(huge_tree):

329

process_node(node)

330

331

# Memory intensive - creates full list

332

all_nodes = list(PreOrderIter(huge_tree)) # Avoid for large trees

333

```