Coverage for src/extratools_core/itertools.py: 0%
52 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-06 00:04 -0700
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-06 00:04 -0700
1from collections.abc import Callable, Iterable, Iterator, Sequence
2from itertools import chain, count, repeat
3from typing import cast
5from toolz.itertoolz import sliding_window
7from .seq import iter_to_seq
8from .typing import Comparable
11def iter_to_grams[T](
12 _iter: Iterable[T],
13 *,
14 n: int,
15 pad: T | None = None,
16) -> Iterable[Sequence[T]]:
17 if pad is not None:
18 _iter = chain(
19 repeat(pad, n - 1),
20 _iter,
21 repeat(pad, n - 1),
22 )
24 return sliding_window(n, _iter)
27def is_sorted[T](
28 seq: Iterable[T],
29 *,
30 key: Callable[[T], Comparable] | None = None,
31 reverse: bool = False,
32) -> bool:
33 local_key: Callable[[T], Comparable]
34 if key is None:
35 def default_key(v: T) -> Comparable:
36 return cast("Comparable", v)
38 local_key = default_key
39 else:
40 local_key = key
42 return all(
43 (
44 local_key(prev) >= local_key(curr) if reverse
45 else local_key(prev) <= local_key(curr)
46 )
47 for prev, curr in sliding_window(2, seq)
48 )
51def filter_by_positions[T](poss: Iterable[int], seq: Iterable[T]) -> Iterable[T]:
52 p: Iterator[int] = iter(poss)
54 pos: int | None = next(p, None)
55 if pos is None:
56 return
58 for i, v in enumerate(seq):
59 if i == pos:
60 yield v
62 pos = next(p, None)
63 if pos is None:
64 return
67def filter_by_others[T](func: Callable[[T, T], bool], _iter: Iterable[T]) -> Iterable[T]:
68 seq: Sequence[T] = iter_to_seq(_iter)
70 filtered_ids: set[int] = set(range(len(seq)))
72 for i, x in enumerate(seq):
73 remove: bool = False
74 for j in filtered_ids:
75 if i == j:
76 continue
78 if not func(x, seq[j]):
79 remove = True
80 break
82 if remove:
83 filtered_ids.remove(i)
85 for i in filtered_ids:
86 yield seq[i]
89def remap[KT, VT](
90 data: Iterable[KT],
91 mapping: dict[KT, VT],
92 *,
93 key: Callable[[KT], VT] | None = None,
94) -> Iterable[VT]:
95 local_key: Callable[[KT], VT]
96 if key is None:
97 c = count(start=0)
99 def default_key(_: KT) -> VT:
100 return cast("VT", next(c))
102 local_key = default_key
103 else:
104 local_key = key
106 k: KT
107 for k in data:
108 yield mapping.setdefault(k, local_key(k))