or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-operations.mddata-manipulation.mdindex.mdpath-access.mdsearch-operations.md

search-operations.mddocs/

0

# Search Operations

1

2

Powerful search capabilities for finding paths and values matching glob patterns in nested dictionaries. These operations support filtering, yielding, and flexible result formats for different use cases.

3

4

## Capabilities

5

6

### Dictionary Search

7

8

Search dictionaries for paths matching glob patterns, returning structured results that preserve the original data hierarchy.

9

10

```python { .api }

11

def search(obj, glob, yielded=False, separator="/", afilter=None, dirs=True):

12

"""

13

Search for paths/values matching glob pattern.

14

15

Parameters:

16

- obj (MutableMapping): Target dictionary to search

17

- glob (Glob): Path pattern as string or sequence

18

- yielded (bool): If True, return generator of (path, value) tuples instead of dict

19

- separator (str): Path separator character (default "/")

20

- afilter (Filter): Optional function to filter results by value

21

- dirs (bool): Include non-leaf (directory-like) nodes in results (default True)

22

23

Returns:

24

dict or generator: Dictionary preserving structure, or generator of (path_str, value) tuples if yielded=True

25

"""

26

```

27

28

#### Usage Examples

29

30

```python

31

import dpath

32

33

data = {

34

"users": {

35

"john": {"age": 30, "city": "NYC", "hobbies": ["reading", "gaming"]},

36

"jane": {"age": 25, "city": "LA", "hobbies": ["hiking", "cooking"]},

37

"bob": {"age": 35, "city": "Chicago"}

38

},

39

"settings": {"theme": "dark", "lang": "en"}

40

}

41

42

# Search with wildcard - returns structured dict

43

cities = dpath.search(data, "users/*/city")

44

# Returns: {'users': {'john': {'city': 'NYC'}, 'jane': {'city': 'LA'}, 'bob': {'city': 'Chicago'}}}

45

46

# Search with yielded=True - returns generator of (path, value) pairs

47

for path, value in dpath.search(data, "users/*/city", yielded=True):

48

print(f"{path}: {value}")

49

# Output:

50

# users/john/city: NYC

51

# users/jane/city: LA

52

# users/bob/city: Chicago

53

54

# Recursive search with **

55

all_values = dpath.search(data, "**/age")

56

# Returns all age values regardless of depth

57

58

# Search excluding directories (dirs=False) - only leaf values

59

leaves_only = dpath.search(data, "users/**", dirs=False)

60

# Excludes intermediate dict objects, only includes final values

61

62

# Filter search results

63

def young_filter(value):

64

return isinstance(value, dict) and value.get("age", 0) < 30

65

66

young_users = dpath.search(data, "users/*", afilter=young_filter)

67

# Returns only jane's record

68

69

# Complex pattern matching

70

hobbies = dpath.search(data, "users/*/hobbies/*") # All individual hobbies

71

first_hobbies = dpath.search(data, "users/*/hobbies/0") # First hobby of each user

72

```

73

74

### Value Extraction

75

76

Extract just the values that match glob patterns, returning a simple list rather than preserving the dictionary structure.

77

78

```python { .api }

79

def values(obj, glob, separator="/", afilter=None, dirs=True):

80

"""

81

Get list of all values matching glob pattern.

82

83

Parameters:

84

- obj (MutableMapping): Target dictionary to search

85

- glob (Glob): Path pattern as string or sequence

86

- separator (str): Path separator character (default "/")

87

- afilter (Filter): Optional function to filter results by value

88

- dirs (bool): Include non-leaf (directory-like) nodes in results (default True)

89

90

Returns:

91

list: List of matching values in order found

92

"""

93

```

94

95

#### Usage Examples

96

97

```python

98

import dpath

99

100

data = {

101

"products": {

102

"electronics": {

103

"laptop": {"price": 1200, "stock": 5},

104

"phone": {"price": 800, "stock": 12}

105

},

106

"books": {

107

"python_guide": {"price": 45, "stock": 20},

108

"data_science": {"price": 60, "stock": 8}

109

}

110

}

111

}

112

113

# Extract all prices as a simple list

114

prices = dpath.values(data, "products/*/*/price")

115

# Returns: [1200, 800, 45, 60]

116

117

# Extract with filtering

118

def expensive_filter(price):

119

return isinstance(price, (int, float)) and price > 50

120

121

expensive_prices = dpath.values(data, "products/*/*/price", afilter=expensive_filter)

122

# Returns: [1200, 800, 60]

123

124

# Extract all product info (directories included by default)

125

all_products = dpath.values(data, "products/*/*")

126

# Returns list of product dictionaries

127

128

# Extract only leaf values (dirs=False)

129

leaf_values = dpath.values(data, "products/**", dirs=False)

130

# Returns: [1200, 5, 800, 12, 45, 20, 60, 8] (all leaf values)

131

132

# Extract with custom separator

133

values_custom_sep = dpath.values(data, "products.*.price", separator=".")

134

```

135

136

## Advanced Search Patterns

137

138

### Glob Pattern Syntax

139

140

dpath supports rich glob patterns for flexible searching:

141

142

```python

143

# Single-level wildcards

144

dpath.search(data, "users/*") # All direct children of users

145

dpath.search(data, "users/*/age") # Age field of all users

146

147

# Multi-level wildcards

148

dpath.search(data, "users/**") # Everything under users (recursive)

149

dpath.search(data, "**/age") # All age fields at any depth

150

151

# Character classes and ranges

152

dpath.search(data, "users/[jb]*") # Users starting with 'j' or 'b'

153

dpath.search(data, "item[0-9]") # Items with single digit suffix

154

155

# Complex combinations

156

dpath.search(data, "*/settings/**/lang") # Lang settings at any depth under any top-level key

157

```

158

159

### Filtering Functions

160

161

Create sophisticated filters to narrow search results:

162

163

```python

164

# Filter by value type

165

def string_filter(value):

166

return isinstance(value, str)

167

168

strings = dpath.values(data, "**", afilter=string_filter)

169

170

# Filter by value content

171

def contains_email(value):

172

return isinstance(value, str) and "@" in value

173

174

emails = dpath.values(data, "**", afilter=contains_email)

175

176

# Filter by dictionary structure

177

def has_required_fields(value):

178

if not isinstance(value, dict):

179

return False

180

return all(field in value for field in ["name", "age", "email"])

181

182

valid_users = dpath.search(data, "users/*", afilter=has_required_fields)

183

184

# Combine filters

185

def active_adult_filter(user):

186

return (isinstance(user, dict) and

187

user.get("active", False) and

188

user.get("age", 0) >= 18)

189

```

190

191

### Working with Generators

192

193

When using `yielded=True`, work efficiently with large datasets:

194

195

```python

196

# Process results incrementally

197

def process_large_dataset(data):

198

for path, value in dpath.search(data, "records/**", yielded=True):

199

# Process one item at a time without loading everything into memory

200

if meets_criteria(value):

201

yield transform(value)

202

203

# Early termination

204

def find_first_match(data, pattern, condition):

205

for path, value in dpath.search(data, pattern, yielded=True):

206

if condition(value):

207

return path, value

208

return None, None

209

210

# Collect specific information

211

paths_and_types = [(path, type(value).__name__)

212

for path, value in dpath.search(data, "**", yielded=True)]

213

```

214

215

## Integration with Other Operations

216

217

Search operations integrate seamlessly with other dpath functions:

218

219

```python

220

# Find then modify

221

matching_paths = [path for path, _ in dpath.search(data, "users/*/active", yielded=True)]

222

for path in matching_paths:

223

dpath.set(data, path, False)

224

225

# Search and extract for processing

226

user_ages = dpath.values(data, "users/*/age")

227

average_age = sum(user_ages) / len(user_ages)

228

229

# Complex workflows

230

active_users = dpath.search(data, "users/*", afilter=lambda u: u.get("active"))

231

for user_path, user_data in dpath.search(active_users, "**", yielded=True):

232

# Process each active user

233

pass

234

```