0
# Enhanced Collections
1
2
Powerful collection classes with functional programming methods, lazy evaluation support, and advanced indexing capabilities. The core is the `L` class which extends Python lists with extensive functional programming operations.
3
4
## Capabilities
5
6
### Enhanced List Class (L)
7
8
The `L` class provides a feature-rich alternative to Python's built-in list with functional programming methods, advanced indexing, and seamless integration with numpy arrays and pandas DataFrames.
9
10
```python { .api }
11
class L(GetAttr, CollBase):
12
"""
13
Enhanced list class with functional programming methods and advanced indexing.
14
15
Features:
16
- Functional operations: map, filter, reduce
17
- Advanced indexing with masks and lists of indices
18
- Method chaining for fluent APIs
19
- Integration with numpy arrays and pandas DataFrames
20
- Lazy evaluation where possible
21
22
Parameters:
23
- items: Initial items for the list
24
- *rest: Additional items to include
25
- use_list: bool, force list conversion
26
- match: Object to match length against
27
"""
28
29
def __init__(self, items=None, *rest, use_list=False, match=None): ...
30
31
# Enhanced indexing
32
def __getitem__(self, idx):
33
"""
34
Retrieve items by index, mask, or list of indices.
35
36
Parameters:
37
- idx: int, slice, boolean mask, or list of indices
38
39
Returns:
40
Single item or new L instance
41
"""
42
43
def __setitem__(self, idx, o):
44
"""
45
Set items at specified indices with broadcasting support.
46
47
Parameters:
48
- idx: int, list of indices, or boolean mask
49
- o: Value(s) to set (broadcast if not iterable)
50
"""
51
52
# Functional operations
53
def map(self, f, *args, **kwargs):
54
"""
55
Apply function to all items, return new L.
56
57
Parameters:
58
- f: Function to apply
59
- *args: Arguments passed to f
60
- **kwargs: Keyword arguments passed to f
61
62
Returns:
63
L: New L with function applied to all items
64
"""
65
66
def filter(self, f=noop, negate=False, **kwargs):
67
"""
68
Filter items by predicate function.
69
70
Parameters:
71
- f: Predicate function (default: noop)
72
- negate: bool, invert the filter condition
73
- **kwargs: Additional arguments
74
75
Returns:
76
L: New L with filtered items
77
"""
78
79
def argwhere(self, f, negate=False, **kwargs):
80
"""
81
Get indices where predicate function returns True.
82
83
Parameters:
84
- f: Predicate function
85
- negate: bool, invert condition
86
- **kwargs: Additional arguments
87
88
Returns:
89
L: Indices where condition is true
90
"""
91
92
def argfirst(self, f, negate=False):
93
"""
94
Get first index where predicate returns True.
95
96
Parameters:
97
- f: Predicate function
98
- negate: bool, invert condition
99
100
Returns:
101
Index of first matching item or None
102
"""
103
```
104
105
### Collection Utilities
106
107
Helper functions for working with collections and creating specialized iterators.
108
109
```python { .api }
110
def mask2idxs(mask):
111
"""
112
Convert boolean mask or index list to integer indices.
113
114
Parameters:
115
- mask: Boolean mask, list of indices, or slice
116
117
Returns:
118
List of integer indices or original slice
119
"""
120
121
def is_indexer(idx):
122
"""
123
Test whether index will select a single item from a list.
124
125
Parameters:
126
- idx: Index to test
127
128
Returns:
129
bool: True if idx selects single item
130
"""
131
132
def cycle(o):
133
"""
134
Like itertools.cycle but handles empty collections gracefully.
135
Creates infinite cycle of [None] if input is empty.
136
137
Parameters:
138
- o: Collection to cycle through
139
140
Returns:
141
Iterator that cycles through items
142
"""
143
144
def zip_cycle(x, *args):
145
"""
146
Like itertools.zip_longest but cycles through all arguments except first.
147
148
Parameters:
149
- x: First iterable (not cycled)
150
- *args: Additional iterables (cycled)
151
152
Returns:
153
Iterator of tuples
154
"""
155
156
def is_bool(x):
157
"""
158
Check whether object is boolean or None.
159
Handles numpy boolean types correctly.
160
161
Parameters:
162
- x: Object to check
163
164
Returns:
165
bool: True if x is boolean-like
166
"""
167
168
def coll_repr(c, max_n=20):
169
"""
170
Create string representation of collection with truncation.
171
172
Parameters:
173
- c: Collection to represent
174
- max_n: Maximum number of items to show
175
176
Returns:
177
str: Truncated string representation
178
"""
179
```
180
181
### Collection Base Class
182
183
Foundation class for creating custom collection types.
184
185
```python { .api }
186
class CollBase:
187
"""
188
Base class for composing collections with standard list interface.
189
190
Features:
191
- Standard sequence protocol (__len__, __getitem__, etc.)
192
- Automatic delegation to internal items storage
193
- Foundation for building custom collection types
194
195
Parameters:
196
- items: Internal storage for collection items
197
"""
198
199
def __init__(self, items): ...
200
def __len__(self): ...
201
def __getitem__(self, k): ...
202
def __setitem__(self, k, v): ...
203
def __delitem__(self, i): ...
204
def __repr__(self): ...
205
def __iter__(self): ...
206
```
207
208
### Configuration Management
209
210
Classes for handling configuration files and settings.
211
212
```python { .api }
213
class Config:
214
"""
215
Configuration management class with file I/O support.
216
217
Features:
218
- Read/write configuration files
219
- Attribute-style access to settings
220
- Support for multiple configuration formats
221
"""
222
223
def save_config_file(file, d, **kwargs):
224
"""
225
Write settings dictionary to configuration file.
226
227
Parameters:
228
- file: Path to configuration file
229
- d: Dictionary of settings to save
230
- **kwargs: Additional options for file writing
231
"""
232
233
def read_config_file(file, **kwargs):
234
"""
235
Read configuration file into dictionary.
236
237
Parameters:
238
- file: Path to configuration file
239
- **kwargs: Additional options for file reading
240
241
Returns:
242
dict: Configuration settings
243
"""
244
```
245
246
### Advanced L Methods
247
248
Extended functionality for the L class including mathematical operations, transformations, and aggregations.
249
250
```python { .api }
251
# Class methods for L creation
252
@classmethod
253
def L.split(cls, s, sep=None, maxsplit=-1):
254
"""Create L by splitting string. Same as str.split but returns L."""
255
256
@classmethod
257
def L.splitlines(cls, s, keepends=False):
258
"""Create L from string lines. Same as str.splitlines but returns L."""
259
260
@classmethod
261
def L.range(cls, a, b=None, step=None):
262
"""Create L from range. Same as range but returns L."""
263
264
# Transformation methods
265
def sorted(self, key=None, reverse=False, cmp=None, **kwargs):
266
"""Return new sorted L. If key is str use attrgetter, if int use itemgetter."""
267
268
def unique(self, sort=False, bidir=False, start=None):
269
"""Return L with unique items in stable order."""
270
271
def shuffle(self):
272
"""Return new L with items shuffled (not in-place)."""
273
274
def enumerate(self):
275
"""Return L of (index, item) tuples."""
276
277
def renumerate(self):
278
"""Return L of (reversed_index, item) tuples."""
279
280
# Attribute and item access
281
def itemgot(self, *idxs):
282
"""Create new L with item at specified indices from all items."""
283
284
def attrgot(self, k, default=None):
285
"""Create new L with attribute k (or dict key k) from all items."""
286
287
# Combining and transformations
288
def starmap(self, f, *args, **kwargs):
289
"""Apply function using itertools.starmap (unpacking arguments)."""
290
291
def zip(self, cycled=False):
292
"""Create new L with zip of all items. Use cycled=True for zip_cycle."""
293
294
def zipwith(self, *rest, cycled=False):
295
"""Zip self with additional iterables."""
296
297
def map_zip(self, f, *args, cycled=False, **kwargs):
298
"""Combine zip and starmap operations."""
299
300
def map_zipwith(self, f, *rest, cycled=False, **kwargs):
301
"""Combine zipwith and starmap operations."""
302
303
def concat(self):
304
"""Concatenate all elements (flatten one level)."""
305
306
# Aggregations
307
def reduce(self, f, initial=None):
308
"""Apply functools.reduce with optional initial value."""
309
310
def sum(self):
311
"""Sum of all numeric items."""
312
313
def product(self):
314
"""Product of all numeric items."""
315
316
# Utilities
317
def val2idx(self):
318
"""Create dictionary mapping values to their indices."""
319
320
def groupby(self, key, val=noop):
321
"""Group items by key function."""
322
323
def map_dict(self, f=noop, *args, **kwargs):
324
"""Create dictionary mapping items to function results."""
325
326
def map_first(self, f=noop, g=noop, *args, **kwargs):
327
"""Get first element after applying map and optional filter g."""
328
329
def setattrs(self, attr, val):
330
"""Set attribute on all items in the collection."""
331
```
332
333
## Usage Examples
334
335
### Basic L Operations
336
337
```python
338
from fastcore.foundation import L
339
340
# Create enhanced list
341
data = L([1, 2, 3, 4, 5])
342
343
# Functional operations with chaining
344
result = (data
345
.filter(lambda x: x % 2 == 0) # Keep even numbers: [2, 4]
346
.map(lambda x: x ** 2) # Square them: [4, 16]
347
.sum()) # Sum: 20
348
349
# Advanced indexing
350
numbers = L(range(10))
351
evens = numbers.filter(lambda x: x % 2 == 0) # L([0, 2, 4, 6, 8])
352
subset = numbers[[1, 3, 5]] # L([1, 3, 5]) - index by list
353
masked = numbers[numbers > 5] # L([6, 7, 8, 9]) - boolean mask
354
```
355
356
### Working with Complex Data
357
358
```python
359
from fastcore.foundation import L
360
361
# Working with objects
362
class Person:
363
def __init__(self, name, age):
364
self.name = name
365
self.age = age
366
def __repr__(self):
367
return f"Person('{self.name}', {self.age})"
368
369
people = L([
370
Person("Alice", 30),
371
Person("Bob", 25),
372
Person("Charlie", 35)
373
])
374
375
# Extract attributes
376
names = people.attrgot('name') # L(['Alice', 'Bob', 'Charlie'])
377
adults = people.filter(lambda p: p.age >= 30) # L([Person('Alice', 30), Person('Charlie', 35)])
378
379
# Working with dictionaries
380
data = L([
381
{"name": "Alice", "score": 95},
382
{"name": "Bob", "score": 87},
383
{"name": "Charlie", "score": 92}
384
])
385
386
high_scores = data.filter(lambda x: x['score'] > 90)
387
names = data.attrgot('name') # Works with dicts too
388
```
389
390
### Advanced Transformations
391
392
```python
393
from fastcore.foundation import L
394
395
# String operations
396
text = "hello world how are you"
397
words = L.split(text) # L(['hello', 'world', 'how', 'are', 'you'])
398
399
# Mathematical operations
400
numbers = L.range(1, 11) # L([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
401
factorial = numbers.reduce(lambda a, b: a * b) # 3628800
402
403
# Grouping and aggregation
404
data = L([
405
('A', 1), ('B', 2), ('A', 3), ('B', 4), ('A', 5)
406
])
407
grouped = data.groupby(lambda x: x[0]) # Group by first element
408
# Returns: {'A': [('A', 1), ('A', 3), ('A', 5)], 'B': [('B', 2), ('B', 4)]}
409
410
# Zipping operations
411
x = L([1, 2, 3])
412
y = L(['a', 'b'])
413
paired = x.zipwith(y, cycled=True) # L([(1, 'a'), (2, 'b'), (3, 'a')])
414
```
415
416
### Integration with NumPy and Pandas
417
418
```python
419
from fastcore.foundation import L
420
import numpy as np
421
import pandas as pd
422
423
# Works with numpy arrays
424
arr = np.array([1, 2, 3, 4, 5])
425
l_arr = L(arr)
426
filtered = l_arr.filter(lambda x: x > 2) # L([3, 4, 5])
427
428
# Works with pandas Series
429
series = pd.Series([10, 20, 30, 40, 50])
430
l_series = L(series)
431
doubled = l_series.map(lambda x: x * 2) # L([20, 40, 60, 80, 100])
432
433
# Boolean indexing like numpy
434
mask = l_arr > 2
435
result = l_arr[mask] # L([3, 4, 5])
436
```