Coverage for src/extratools_core/itertools.py: 0%
44 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-05 23:54 -0700
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-05 23:54 -0700
1from collections.abc import Callable, Iterable, Sequence
2from itertools import chain, count, repeat
3from typing import Iterator, cast
5from toolz.itertoolz import sliding_window
7from .seq import iter_to_seq
10def iter_to_grams[T](
11 _iter: Iterable[T],
12 *,
13 n: int,
14 pad: T | None = None,
15) -> Iterable[Sequence[T]]:
16 if pad is not None:
17 _iter = chain(
18 repeat(pad, n - 1),
19 _iter,
20 repeat(pad, n - 1),
21 )
23 return sliding_window(n, _iter)
26def filter_by_positions[T](poss: Iterable[int], seq: Iterable[T]) -> Iterable[T]:
27 p: Iterator[int] = iter(poss)
29 pos: int | None = next(p, None)
30 if pos is None:
31 return
33 for i, v in enumerate(seq):
34 if i == pos:
35 yield v
37 pos = next(p, None)
38 if pos is None:
39 return
42def filter_by_others[T](func: Callable[[T, T], bool], _iter: Iterable[T]) -> Iterable[T]:
43 seq: Sequence[T] = iter_to_seq(_iter)
45 filtered_ids: set[int] = set(range(len(seq)))
47 for i, x in enumerate(seq):
48 remove: bool = False
49 for j in filtered_ids:
50 if i == j:
51 continue
53 if not func(x, seq[j]):
54 remove = True
55 break
57 if remove:
58 filtered_ids.remove(i)
60 for i in filtered_ids:
61 yield seq[i]
64def remap[KT, VT](
65 data: Iterable[KT],
66 mapping: dict[KT, VT],
67 *,
68 key: Callable[[KT], VT] | None = None,
69) -> Iterable[VT]:
70 local_key: Callable[[KT], VT]
71 if key is None:
72 c = count(start=0)
74 def default_key(_: KT) -> VT:
75 return cast("VT", next(c))
77 local_key = default_key
78 else:
79 local_key = key
81 k: KT
82 for k in data:
83 yield mapping.setdefault(k, local_key(k))