0
# Advanced Utilities
1
2
Specialized utilities for complex operations and advanced use cases.
3
4
## Capabilities
5
6
### Flattening Operations
7
8
Functions for flattening nested structures.
9
10
```python { .api }
11
def flatten(iterable: Iterable[Iterable[Any]]) -> Iterator[Any]: ...
12
def collapse(iterable: Iterable[Any], base_type: type | tuple[type, ...] = None, levels: int = None) -> Iterator[Any]: ...
13
```
14
15
**Usage:**
16
17
```python
18
from more_itertools import flatten, collapse
19
20
# Simple flattening of one level
21
nested = [[1, 2], [3, 4], [5, 6]]
22
flat = list(flatten(nested)) # [1, 2, 3, 4, 5, 6]
23
24
# Deep flattening with collapse
25
deeply_nested = [1, [2, [3, [4, 5]], 6], 7]
26
deep_flat = list(collapse(deeply_nested)) # [1, 2, 3, 4, 5, 6, 7]
27
28
# Control flattening levels
29
partially_flat = list(collapse(deeply_nested, levels=1)) # [1, 2, [3, [4, 5]], 6, 7]
30
31
# Preserve certain types from flattening
32
mixed = [1, "hello", [2, 3], "world", [4, 5]]
33
flat_preserve_str = list(collapse(mixed, base_type=str)) # [1, "hello", 2, 3, "world", 4, 5]
34
```
35
36
### Mapping Operations
37
38
Advanced mapping and transformation functions.
39
40
```python { .api }
41
def join_mappings(*mappings: Mapping[Any, Any]) -> dict[Any, list[Any]]: ...
42
def map_reduce(iterable: Iterable[Any], keyfunc: Callable[[Any], Any], valuefunc: Callable[[Any], Any] = None, reducefunc: Callable[[list[Any]], Any] = None) -> dict[Any, Any]: ...
43
def groupby_transform(iterable: Iterable[Any], keyfunc: Callable[[Any], Any] = None, valuefunc: Callable[[Any], Any] = None, reducefunc: Callable[[list[Any]], Any] = list) -> dict[Any, Any]: ...
44
```
45
46
**Usage:**
47
48
```python
49
from more_itertools import join_mappings, map_reduce, groupby_transform
50
51
# Join multiple mappings
52
map1 = {'a': 1, 'b': 2}
53
map2 = {'a': 3, 'c': 4}
54
map3 = {'b': 5, 'd': 6}
55
56
joined = join_mappings(map1, map2, map3)
57
# {'a': [1, 3], 'b': [2, 5], 'c': [4], 'd': [6]}
58
59
# Map-reduce operation
60
data = ['apple', 'banana', 'apricot', 'blueberry', 'cherry']
61
# Group by first letter, count items
62
result = map_reduce(
63
data,
64
keyfunc=lambda x: x[0], # Group by first letter
65
valuefunc=lambda x: 1, # Count each item as 1
66
reducefunc=sum # Sum the counts
67
)
68
# {'a': 2, 'b': 2, 'c': 1}
69
70
# Group and transform
71
students = [
72
{'name': 'Alice', 'grade': 85, 'subject': 'math'},
73
{'name': 'Bob', 'grade': 90, 'subject': 'math'},
74
{'name': 'Alice', 'grade': 78, 'subject': 'science'},
75
{'name': 'Bob', 'grade': 88, 'subject': 'science'}
76
]
77
78
# Group by name, collect grades
79
grades_by_student = groupby_transform(
80
students,
81
keyfunc=lambda s: s['name'],
82
valuefunc=lambda s: s['grade']
83
)
84
# {'Alice': [85, 78], 'Bob': [90, 88]}
85
86
# Group by name, get average grade
87
avg_grades = groupby_transform(
88
students,
89
keyfunc=lambda s: s['name'],
90
valuefunc=lambda s: s['grade'],
91
reducefunc=lambda grades: sum(grades) / len(grades)
92
)
93
# {'Alice': 81.5, 'Bob': 89.0}
94
```
95
96
### Time-Limited Operations
97
98
Classes for controlling iteration time.
99
100
```python { .api }
101
class time_limited:
102
"""Iterator that yields items until time limit expires."""
103
104
def __init__(self, limit_seconds, iterable):
105
"""
106
Initialize time-limited iterator.
107
108
Args:
109
limit_seconds: Maximum time in seconds to iterate
110
iterable: The iterable to time-limit
111
"""
112
113
def __iter__(self):
114
"""Return iterator object."""
115
116
def __next__(self):
117
"""Return next item, checking time limit."""
118
119
@property
120
def timed_out(self):
121
"""True if time limit was exceeded."""
122
```
123
124
**Usage:**
125
126
```python
127
from more_itertools import time_limited
128
import time
129
130
# Generate data but limit processing time
131
def slow_generator():
132
i = 0
133
while True:
134
time.sleep(0.1) # Simulate slow operation
135
yield i
136
i += 1
137
138
# Process for at most 1 second
139
limited = time_limited(1.0, slow_generator())
140
results = list(limited) # Will stop after ~1 second
141
print(f"Processed {len(results)} items in ~1 second")
142
print(f"Timed out: {limited.timed_out}")
143
```
144
145
### Numeric Range Operations
146
147
Classes for advanced numeric range generation.
148
149
```python { .api }
150
class numeric_range:
151
"""Extended range() for any numeric types."""
152
153
def __init__(self, *args):
154
"""
155
Initialize numeric range.
156
157
Args:
158
*args: 1, 2, or 3 arguments like built-in range():
159
- (stop): start=0, step=1
160
- (start, stop): step=1
161
- (start, stop, step): all specified
162
"""
163
164
def __iter__(self):
165
"""Return iterator over range values."""
166
167
def __len__(self):
168
"""Return length of range."""
169
170
def __getitem__(self, key):
171
"""Get item by index or slice."""
172
173
def __contains__(self, value):
174
"""Test if value is in range."""
175
```
176
177
**Usage:**
178
179
```python
180
from more_itertools import numeric_range
181
from decimal import Decimal
182
183
# Floating-point range with precise stepping
184
float_range = list(numeric_range(0.0, 1.0, 0.1))
185
# [0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
186
187
# Decimal arithmetic for financial calculations
188
decimal_range = list(numeric_range(Decimal('0'), Decimal('1'), Decimal('0.1')))
189
# Avoids floating-point precision issues
190
191
# Works like built-in range but with any numeric type
192
range_obj = numeric_range(Decimal('2.5'), Decimal('10.5'), Decimal('1.5'))
193
print(len(range_obj)) # Supports len()
194
print(Decimal('5') in range_obj) # Supports membership testing
195
```
196
197
### Extended Slicing
198
199
Enhanced slicing operations.
200
201
```python { .api }
202
class islice_extended:
203
"""Extended islice with negative index support."""
204
205
def __init__(self, iterable, *args):
206
"""
207
Initialize extended islice.
208
209
Args:
210
iterable: The iterable to slice
211
*args: Optional start, stop, step like itertools.islice
212
"""
213
214
def __iter__(self):
215
"""Return iterator object."""
216
217
def __next__(self):
218
"""Return next item."""
219
220
def __getitem__(self, key):
221
"""Support slice notation.
222
223
Args:
224
key: A slice object
225
226
Returns:
227
New islice_extended with slice applied
228
"""
229
```
230
231
**Usage:**
232
233
```python
234
from more_itertools import islice_extended
235
236
data = range(20)
237
238
# Standard slicing
239
normal_slice = list(islice_extended(data, 5, 15, 2)) # [5, 7, 9, 11, 13]
240
241
# Negative indices (enhanced feature)
242
data_list = list(range(10)) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
243
end_slice = list(islice_extended(data_list, -3, None)) # [7, 8, 9]
244
245
# Slice notation support
246
iterator = islice_extended(range(100))
247
result = list(iterator[10:20:2]) # [10, 12, 14, 16, 18]
248
```
249
250
### Reshaping Operations
251
252
Functions for reshaping sequences.
253
254
```python { .api }
255
def reshape(iterable: Iterable[Any], shape: tuple[int, ...]) -> Iterator[Any]: ...
256
```
257
258
**Usage:**
259
260
```python
261
from more_itertools import reshape
262
263
# Reshape flat data into multi-dimensional structure
264
data = range(12)
265
matrix = list(reshape(data, (3, 4)))
266
# Creates 3 rows of 4 elements each:
267
# [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
268
269
# 3D reshape
270
cube = list(reshape(range(24), (2, 3, 4)))
271
# Creates 2 layers of 3x4 matrices
272
```
273
274
### Double Star Map
275
276
Enhanced mapping operations.
277
278
```python { .api }
279
def doublestarmap(func: Callable[..., Any], iterable: Iterable[tuple[tuple[Any, ...], dict[str, Any]]]) -> Iterator[Any]: ...
280
```
281
282
**Usage:**
283
284
```python
285
from more_itertools import doublestarmap
286
287
# Apply function with both positional and keyword arguments
288
def greet(name, age, title="Mr/Ms"):
289
return f"{title} {name} (age {age})"
290
291
# Each item is (args_tuple, kwargs_dict)
292
data = [
293
(("Alice", 25), {"title": "Dr"}),
294
(("Bob", 30), {}),
295
(("Charlie", 35), {"title": "Prof"})
296
]
297
298
greetings = list(doublestarmap(greet, data))
299
# ["Dr Alice (age 25)", "Mr/Ms Bob (age 30)", "Prof Charlie (age 35)"]
300
```
301
302
### Random Interleaving
303
304
Functions for random interleaving of multiple iterables.
305
306
```python { .api }
307
def interleave_randomly(*iterables):
308
"""
309
Randomly interleave items from multiple iterables.
310
311
Args:
312
*iterables: Variable number of iterables to interleave
313
314
Returns:
315
Iterator yielding items in random order while preserving internal sequence
316
"""
317
```
318
319
**Usage:**
320
321
```python
322
from more_itertools import interleave_randomly
323
324
# Random interleaving preserves internal order
325
lists = [[1, 2, 3], ['a', 'b', 'c'], [True, False]]
326
result = list(interleave_randomly(*lists))
327
# Result could be: [1, 'a', True, 2, 'b', False, 3, 'c']
328
# Note: Order is random but each list's internal sequence is preserved
329
```
330
331
### Inclusive Takewhile
332
333
Enhanced takewhile operations.
334
335
```python { .api }
336
def takewhile_inclusive(predicate, iterable):
337
"""
338
Take items while predicate is true, including first failing item.
339
340
Args:
341
predicate: Function returning True/False for each element
342
iterable: Input sequence to process
343
344
Returns:
345
Iterator yielding elements until predicate fails, including failing element
346
"""
347
```
348
349
**Usage:**
350
351
```python
352
from more_itertools import takewhile_inclusive
353
from itertools import takewhile
354
355
# Compare standard takewhile vs takewhile_inclusive
356
data = [1, 3, 5, 8, 2, 4]
357
predicate = lambda x: x < 6
358
359
standard = list(takewhile(predicate, data)) # [1, 3, 5]
360
inclusive = list(takewhile_inclusive(predicate, data)) # [1, 3, 5, 8]
361
# Includes the first element that fails the predicate
362
```
363
364
### Context Manager Iteration
365
366
Functions for context-managed iteration.
367
368
```python { .api }
369
def with_iter(context_manager):
370
"""
371
Wrap iterable in with statement for automatic cleanup.
372
373
Args:
374
context_manager: Context manager that yields an iterable
375
376
Returns:
377
Iterator that properly closes context manager when exhausted
378
"""
379
```
380
381
**Usage:**
382
383
```python
384
from more_itertools import with_iter
385
386
# Automatically close file when iteration completes
387
lines = list(with_iter(open('data.txt')))
388
389
# Works with any context manager that returns an iterable
390
with open('output.txt', 'w') as f:
391
for line in with_iter(open('input.txt')):
392
f.write(line.upper())
393
# input.txt is automatically closed when iteration finishes
394
```
395
396
### Exception Suppression
397
398
Functions for suppressing exceptions during iteration.
399
400
```python { .api }
401
def iter_suppress(iterable, *exceptions):
402
"""
403
Iterate while suppressing specified exceptions.
404
405
Args:
406
iterable: Input iterable to process
407
*exceptions: Exception types to suppress during iteration
408
409
Returns:
410
Iterator that stops gracefully when specified exceptions occur
411
"""
412
```
413
414
**Usage:**
415
416
```python
417
from more_itertools import iter_suppress
418
419
def risky_generator():
420
for i in range(10):
421
if i == 5:
422
raise ValueError("Something went wrong")
423
yield i
424
425
# Suppress ValueError and get partial results
426
safe_iter = iter_suppress(risky_generator(), ValueError)
427
result = list(safe_iter) # [0, 1, 2, 3, 4] - stops at exception
428
429
# Multiple exception types
430
result = list(iter_suppress(some_iter, ValueError, TypeError, KeyError))
431
```