Iterables & Sequences Utilities¶
The escudeiro.misc.iterx
module provides advanced utilities for working with iterables, sequences, and async iterables in Python. It includes functions for windowing, mapping, filtering, flattening, grouping, and moreāsupporting both synchronous and asynchronous workflows.
Why?¶
Python's standard library offers many tools for iteration, but common patterns like sliding windows, async mapping/filtering, or flattening nested structures often require verbose or repetitive code. This module provides concise, type-safe, and feature-rich helpers for these scenarios.
Features¶
- Sliding windows for sync and async iterables
- Async mapping, filtering, reducing and enumeration
- Flattening of nested sequences
- Type-based filtering (
isinstance
,issubclass
) - Carry mapping (preserve original values)
- Safe next/anext with default
- Dictionary inversion and grouping
Usage¶
Moving Window¶
from escudeiro.misc.iterx import moving_window
list(moving_window([1, 2, 3, 4, 5], 3))
# Output: [(1, 2, 3), (4, 5)]
Async Moving Window¶
from escudeiro.misc.iterx import amoving_window, aislice
import asyncio
async def main():
async def gen():
for i in range(7):
yield i
async for window in amoving_window(gen(), 3):
print(window)
# Output: [0, 1, 2], [3, 4, 5], [6]
Async Map/Filter/Reduce¶
from escudeiro.misc.iterx import amap, afilter, areduce
async def main():
async def gen():
for i in range(5):
yield i
# Map
async for x in amap(lambda x: x * 2, gen()):
print(x)
# Filter
async for x in afilter(lambda x: x % 2 == 0, gen()):
print(x)
# Reduce
result = await areduce(lambda a, b: a + b, gen(), 0)
print(result)
Flatten Nested Sequences¶
from escudeiro.misc.iterx import flatten
flatten([1, [2, 3], [4, [5, 6]]])
# Output: [1, 2, 3, 4, 5, 6]
Filter by Type¶
from escudeiro.misc.iterx import filter_isinstance
list(filter_isinstance(str, [1, "hello", 2, "world"]))
# Output: ["hello", "world"]
Invert Dictionary¶
from escudeiro.misc.iterx import invert_dict
invert_dict({'a': 1, 'b': 2})
# Output: {1: 'a', 2: 'b'}
API Reference¶
Windowing¶
moving_window
¶
def moving_window[T](
iterable: Iterable[T],
window_size: int,
cast: Callable[[Iterator[T]], Sequence[T]] = tuple,
) -> Iterable[Sequence[T]]:
amoving_window
¶
async def amoving_window[T](
iterable: AsyncIterable[T],
window_size: int,
) -> AsyncIterable[Sequence[T]]:
aislice
¶
async def aislice[T](
iterable: AsyncIterable[T],
start: int | None = None,
stop: int | None = None,
step: int | None = None,
) -> AsyncIterable[T]:
Mapping & Filtering¶
amap
¶
async def amap[V, T](
predicate: Callable[[V], T] | Callable[[V], Coroutine[Any, Any, T]],
iterable: AsyncIterable[V],
) -> AsyncIterable[T]:
afilter
¶
async def afilter[V](
predicate: Callable[[V], bool] | Callable[[V], Coroutine[Any, Any, bool]],
iterable: AsyncIterable[V],
) -> AsyncIterable[V]:
areduce
¶
async def areduce[V, T](
predicate: Callable[[T, V], T] | Callable[[T, V], Coroutine[Any, Any, T]],
iterable: AsyncIterable[V],
initial: T | object = _reduce_sentinel,
) -> T | V:
aenumerate
¶
async def aenumerate[T](
iterable: AsyncIterable[T], start: int = 0
) -> AsyncIterable[tuple[int, T]]:
aany
, aall
¶
async def aany[T](iterable: AsyncIterable[T], predicate=bool) -> bool
async def aall[T](iterable: AsyncIterable[T], predicate=bool) -> bool
Sequence Utilities¶
flatten
¶
def flatten(sequence: Sequence[Any]) -> Sequence[Any]:
exclude_none
¶
def exclude_none[SequenceT: SequenceTypes](sequence: SequenceT) -> SequenceT:
None
from sequences.
next_or
, anext_or
¶
def next_or[T, D](iterable: Iterable[T], default: D = None) -> T | D
async def anext_or[T, D](iterable: AsyncIterable[T], default: D = None) -> T | D
Carry Mapping¶
carrymap
, acarrymap
¶
def carrymap[T, U](predicate: Callable[[T], U], iterable: Iterable[T]) -> Iterable[tuple[U, T]]
async def acarrymap[U, T](predicate: Callable[[T], Coroutine[Any, Any, U]], iterable: AsyncIterable[T]) -> AsyncIterable[tuple[U, T]]
astarmap
, acarrystarmap
¶
async def astarmap[*Ts, U](predicate: Callable[[*Ts], Coroutine[Any, Any, U]], iterable: AsyncIterable[tuple[*Ts]]) -> AsyncIterable[U]
async def acarrystarmap[*Ts, U](predicate: Callable[[*Ts], Coroutine[Any, Any, U]], iterable: AsyncIterable[tuple[*Ts]]) -> AsyncIterable[tuple[U, tuple[*Ts]]]
Type Filtering¶
filter_isinstance
¶
def filter_isinstance[T](bases: type[T] | tuple[type[T], ...], iterable: Iterable[Any]) -> filter[T]
isinstance
.
filter_issubclass
¶
def filter_issubclass[T](bases: type[T], iterable: Iterable[Any]) -> filter[T]
issubclass
.
Dictionary Utilities¶
invert_dict
¶
def invert_dict[K: Hashable, V: Hashable](mapping: Mapping[K, V]) -> Mapping[V, K]
group_values
¶
def group_values[K, V](vals: Collection[dict[K, V]], group_by_key: K) -> dict[K, list[dict[K, V]]]
Notes¶
- Async utilities require Python 3.8+.
- Many functions are type-annotated for static analysis.
- Use
flatten
andexclude_none
for deep sequence cleaning.