Coverage for src/extratools_core/seq/__init__.py: 33%
42 statements
« prev ^ index » next coverage.py v7.8.1, created at 2025-05-23 02:35 -0700
« prev ^ index » next coverage.py v7.8.1, created at 2025-05-23 02:35 -0700
1import operator
2from collections import Counter
3from collections.abc import Callable, Iterable, Iterator, Mapping
4from itertools import groupby, repeat
5from typing import Any, cast
7from toolz import itertoolz, unique
9from ..typing import Comparable
10from .common import iter_to_seq # noqa: F401
13def sorted_by_rank[T](
14 data: Iterable[T],
15 ranks: Iterable[Comparable],
16 *,
17 _reverse: bool = False,
18) -> list[T]:
19 return [
20 v
21 for v, _ in sorted(
22 zip(data, ranks, strict=True),
23 key=lambda x: x[1],
24 reverse=_reverse,
25 )
26 ]
29def compress[T](
30 data: Iterable[T],
31 key: Callable[[T], Any] | None = None,
32) -> Iterable[tuple[T, int]]:
33 for k, g in groupby(data, key=key):
34 yield (k, itertoolz.count(g))
37def decompress[T](data: Iterable[tuple[T, int]]) -> Iterable[T]:
38 for k, n in data:
39 yield from repeat(k, n)
42def to_deltas[T](
43 data: Iterable[T],
44 op: Callable[[T, T], T] = operator.sub,
45) -> Iterable[T]:
46 seq: Iterator[T] = iter(data)
48 curr: T | None = next(seq, None)
49 if curr is None:
50 return
52 yield curr
54 prev: T = curr
55 for curr in seq:
56 yield op(curr, prev)
58 prev = curr
61def from_deltas[T](
62 data: Iterable[T],
63 op: Callable[[T, T], T] = operator.add,
64) -> Iterable[T]:
65 seq: Iterator[T] = iter(data)
67 curr: T | None = next(seq, None)
68 if curr is None:
69 return
71 yield curr
73 prev: T = curr
74 for curr in seq:
75 res: T = op(prev, curr)
76 yield res
78 prev = res
81def key_frequencies[KT, VT](
82 *seqs: Iterable[KT],
83 key: Callable[[KT], VT] | None = None,
84) -> Mapping[VT, int]:
85 c: Counter[VT] = Counter()
86 for seq in seqs:
87 c.update(cast("Iterable[VT]", unique(seq, key=key)))
89 return c