0
# Dictionary Operations
1
2
Immutable dictionary manipulation functions including merging, filtering, mapping, and nested access operations. All functions return new dictionaries without modifying input dictionaries, following functional programming principles.
3
4
## Capabilities
5
6
### Dictionary Combination
7
8
Functions for combining multiple dictionaries in various ways.
9
10
```python { .api }
11
def merge(*dicts, **kwargs):
12
"""
13
Merge collection of dictionaries into a single dictionary.
14
15
Parameters:
16
- *dicts: dictionaries to merge (later ones take precedence)
17
- factory: dict-like constructor for result type (optional)
18
19
Returns:
20
New dictionary with merged key-value pairs
21
"""
22
23
def merge_with(func, *dicts, **kwargs):
24
"""
25
Merge dictionaries and apply function to combined values.
26
27
When multiple dictionaries contain the same key, all values
28
for that key are passed to func as a list.
29
30
Parameters:
31
- func: function to apply to combined values (takes list, returns value)
32
- *dicts: dictionaries to merge
33
- factory: dict-like constructor for result type (optional)
34
35
Returns:
36
New dictionary with func applied to combined values
37
"""
38
```
39
40
### Dictionary Transformation
41
42
Functions for applying transformations to dictionary keys, values, or items.
43
44
```python { .api }
45
def valmap(func, d, factory=dict):
46
"""
47
Apply function to all values in dictionary.
48
49
Parameters:
50
- func: function to apply to each value
51
- d: input dictionary
52
- factory: constructor for result dictionary type
53
54
Returns:
55
New dictionary with transformed values
56
"""
57
58
def keymap(func, d, factory=dict):
59
"""
60
Apply function to all keys in dictionary.
61
62
Parameters:
63
- func: function to apply to each key
64
- d: input dictionary
65
- factory: constructor for result dictionary type
66
67
Returns:
68
New dictionary with transformed keys
69
"""
70
71
def itemmap(func, d, factory=dict):
72
"""
73
Apply function to all (key, value) pairs in dictionary.
74
75
Parameters:
76
- func: function taking (key, value) and returning (new_key, new_value)
77
- d: input dictionary
78
- factory: constructor for result dictionary type
79
80
Returns:
81
New dictionary with transformed items
82
"""
83
```
84
85
### Dictionary Filtering
86
87
Functions for filtering dictionaries based on keys, values, or items.
88
89
```python { .api }
90
def valfilter(predicate, d, factory=dict):
91
"""
92
Filter dictionary items by values.
93
94
Parameters:
95
- predicate: function that returns True/False for each value
96
- d: input dictionary
97
- factory: constructor for result dictionary type
98
99
Returns:
100
New dictionary containing only items where predicate(value) is True
101
"""
102
103
def keyfilter(predicate, d, factory=dict):
104
"""
105
Filter dictionary items by keys.
106
107
Parameters:
108
- predicate: function that returns True/False for each key
109
- d: input dictionary
110
- factory: constructor for result dictionary type
111
112
Returns:
113
New dictionary containing only items where predicate(key) is True
114
"""
115
116
def itemfilter(predicate, d, factory=dict):
117
"""
118
Filter dictionary items by (key, value) pairs.
119
120
Parameters:
121
- predicate: function that returns True/False for each (key, value) pair
122
- d: input dictionary
123
- factory: constructor for result dictionary type
124
125
Returns:
126
New dictionary containing only items where predicate(key, value) is True
127
"""
128
```
129
130
### Dictionary Manipulation
131
132
Functions for adding, removing, and updating dictionary entries.
133
134
```python { .api }
135
def assoc(d, key, value, factory=dict):
136
"""
137
Return new dictionary with key-value pair added/updated.
138
139
Parameters:
140
- d: input dictionary
141
- key: key to associate with value
142
- value: value to associate with key
143
- factory: constructor for result dictionary type
144
145
Returns:
146
New dictionary with key mapped to value
147
"""
148
149
def dissoc(d, *keys, **kwargs):
150
"""
151
Return new dictionary with specified keys removed.
152
153
Parameters:
154
- d: input dictionary
155
- *keys: keys to remove from dictionary
156
- factory: constructor for result dictionary type (optional)
157
158
Returns:
159
New dictionary with specified keys removed
160
"""
161
162
def assoc_in(d, keys, value, factory=dict):
163
"""
164
Return new dictionary with nested key-value pair added/updated.
165
166
Creates nested dictionary structure as needed.
167
168
Parameters:
169
- d: input dictionary (possibly nested)
170
- keys: sequence of keys defining path to nested value
171
- value: value to set at nested location
172
- factory: constructor for result dictionary type
173
174
Returns:
175
New nested dictionary with value set at specified path
176
"""
177
178
def update_in(d, keys, func, default=None, factory=dict):
179
"""
180
Update value in nested dictionary by applying function.
181
182
Parameters:
183
- d: input dictionary (possibly nested)
184
- keys: sequence of keys defining path to nested value
185
- func: function to apply to current value at path
186
- default: default value if path doesn't exist
187
- factory: constructor for result dictionary type
188
189
Returns:
190
New nested dictionary with updated value at path
191
"""
192
193
def get_in(keys, coll, default=None, no_default=False):
194
"""
195
Get value from nested dictionary/collection.
196
197
Access nested value using sequence of keys: coll[keys[0]][keys[1]]...[keys[n]]
198
199
Parameters:
200
- keys: sequence of keys defining path to nested value
201
- coll: nested dictionary or collection
202
- default: value to return if path doesn't exist
203
- no_default: if True, raise KeyError when path doesn't exist
204
205
Returns:
206
Value at nested path, or default if path doesn't exist
207
"""
208
```
209
210
## Usage Examples
211
212
### Dictionary Merging and Combination
213
214
```python
215
from toolz import merge, merge_with
216
from operator import add
217
218
# Basic merging
219
config_defaults = {'host': 'localhost', 'port': 8080, 'debug': False}
220
user_config = {'port': 3000, 'debug': True}
221
config = merge(config_defaults, user_config)
222
# {'host': 'localhost', 'port': 3000, 'debug': True}
223
224
# Merge with function to combine values
225
sales_q1 = {'apples': 100, 'oranges': 80, 'bananas': 60}
226
sales_q2 = {'apples': 120, 'oranges': 70, 'bananas': 90}
227
total_sales = merge_with(add, sales_q1, sales_q2)
228
# {'apples': 220, 'oranges': 150, 'bananas': 150}
229
230
# Merge multiple dictionaries
231
results = merge_with(
232
lambda values: sum(values) / len(values), # average
233
{'score': 85}, {'score': 90}, {'score': 78}
234
)
235
# {'score': 84.33333333333333}
236
```
237
238
### Dictionary Transformation
239
240
```python
241
from toolz import valmap, keymap, itemmap
242
243
# Transform values
244
prices = {'apple': 1.20, 'banana': 0.80, 'orange': 1.50}
245
prices_cents = valmap(lambda x: int(x * 100), prices)
246
# {'apple': 120, 'banana': 80, 'orange': 150}
247
248
# Transform keys
249
data = {'firstName': 'John', 'lastName': 'Doe', 'emailAddress': 'john@example.com'}
250
snake_case = keymap(lambda k: ''.join('_' + c.lower() if c.isupper() else c for c in k).lstrip('_'), data)
251
# {'first_name': 'John', 'last_name': 'Doe', 'email_address': 'john@example.com'}
252
253
# Transform both keys and values
254
inventory = {'APPLES': 50, 'BANANAS': 30, 'ORANGES': 25}
255
formatted = itemmap(lambda k, v: (k.lower().capitalize(), f"{v} units"), inventory)
256
# {'Apples': '50 units', 'Bananas': '30 units', 'Oranges': '25 units'}
257
```
258
259
### Dictionary Filtering
260
261
```python
262
from toolz import valfilter, keyfilter, itemfilter
263
264
# Filter by values
265
scores = {'alice': 85, 'bob': 92, 'charlie': 78, 'diana': 96}
266
high_scores = valfilter(lambda score: score >= 90, scores)
267
# {'bob': 92, 'diana': 96}
268
269
# Filter by keys
270
data = {'user_name': 'john', 'user_email': 'john@example.com', 'temp_token': 'abc123', 'user_id': 42}
271
user_data = keyfilter(lambda key: key.startswith('user_'), data)
272
# {'user_name': 'john', 'user_email': 'john@example.com', 'user_id': 42}
273
274
# Filter by items (key-value pairs)
275
products = {'laptop': 1200, 'mouse': 25, 'keyboard': 80, 'monitor': 300}
276
affordable = itemfilter(lambda k, v: v <= 100, products)
277
# {'mouse': 25, 'keyboard': 80}
278
```
279
280
### Nested Dictionary Operations
281
282
```python
283
from toolz import assoc_in, update_in, get_in
284
285
# Working with nested data
286
user = {
287
'name': 'Alice',
288
'profile': {
289
'age': 30,
290
'address': {
291
'city': 'New York',
292
'country': 'USA'
293
}
294
}
295
}
296
297
# Access nested values
298
city = get_in(['profile', 'address', 'city'], user)
299
# 'New York'
300
301
# Set nested values (creates structure as needed)
302
updated_user = assoc_in(user, ['profile', 'address', 'zipcode'], '10001')
303
# Adds zipcode to the nested address
304
305
# Update nested values with function
306
aged_user = update_in(user, ['profile', 'age'], lambda age: age + 1)
307
# Increments age from 30 to 31
308
309
# Handle missing paths gracefully
310
phone = get_in(['profile', 'contact', 'phone'], user, 'No phone available')
311
# 'No phone available' (since path doesn't exist)
312
```
313
314
### Advanced Dictionary Patterns
315
316
```python
317
from toolz import pipe, merge, valmap, keyfilter, assoc
318
319
# Complex data processing pipeline
320
raw_data = {
321
'users': [
322
{'name': 'Alice', 'age': 30, 'active': True},
323
{'name': 'Bob', 'age': 25, 'active': False},
324
{'name': 'Charlie', 'age': 35, 'active': True}
325
]
326
}
327
328
# Process user data
329
processed = pipe(
330
raw_data,
331
lambda d: assoc(d, 'active_users', [u for u in d['users'] if u['active']]),
332
lambda d: assoc(d, 'user_count', len(d['users'])),
333
lambda d: assoc(d, 'avg_age', sum(u['age'] for u in d['users']) / len(d['users'])),
334
lambda d: keyfilter(lambda k: k != 'users', d) # Remove original users list
335
)
336
# {
337
# 'active_users': [{'name': 'Alice', 'age': 30, 'active': True}, ...],
338
# 'user_count': 3,
339
# 'avg_age': 30.0
340
# }
341
```
342
343
### Configuration Management
344
345
```python
346
from toolz import merge, assoc_in, get_in
347
348
# Application configuration with defaults and overrides
349
default_config = {
350
'database': {
351
'host': 'localhost',
352
'port': 5432,
353
'name': 'myapp'
354
},
355
'api': {
356
'timeout': 30,
357
'retries': 3
358
},
359
'features': {
360
'caching': True,
361
'logging': True
362
}
363
}
364
365
# Environment-specific overrides
366
production_overrides = {
367
'database': {
368
'host': 'prod-db.example.com',
369
'port': 5432
370
},
371
'api': {
372
'timeout': 60
373
},
374
'features': {
375
'caching': True
376
}
377
}
378
379
# Merge configurations
380
config = merge(default_config, production_overrides)
381
382
# Update specific nested values
383
config = assoc_in(config, ['database', 'ssl'], True)
384
config = assoc_in(config, ['api', 'rate_limit'], 1000)
385
386
# Access configuration values
387
db_host = get_in(['database', 'host'], config)
388
api_timeout = get_in(['api', 'timeout'], config)
389
```