smartarr 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- smartarr-0.1.0/LICENSE +21 -0
- smartarr-0.1.0/PKG-INFO +149 -0
- smartarr-0.1.0/README.md +124 -0
- smartarr-0.1.0/pyproject.toml +37 -0
- smartarr-0.1.0/setup.cfg +4 -0
- smartarr-0.1.0/setup.py +40 -0
- smartarr-0.1.0/src/smartarr/__init__.py +4 -0
- smartarr-0.1.0/src/smartarr/_backend.py +25 -0
- smartarr-0.1.0/src/smartarr/_pybackend.py +106 -0
- smartarr-0.1.0/src/smartarr/_smartarr.c +621 -0
- smartarr-0.1.0/src/smartarr/adapters.py +78 -0
- smartarr-0.1.0/src/smartarr/api.py +243 -0
- smartarr-0.1.0/src/smartarr.egg-info/PKG-INFO +149 -0
- smartarr-0.1.0/src/smartarr.egg-info/SOURCES.txt +17 -0
- smartarr-0.1.0/src/smartarr.egg-info/dependency_links.txt +1 -0
- smartarr-0.1.0/src/smartarr.egg-info/requires.txt +3 -0
- smartarr-0.1.0/src/smartarr.egg-info/top_level.txt +1 -0
- smartarr-0.1.0/tests/test_smartarr.py +92 -0
smartarr-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OpenAI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
smartarr-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: smartarr
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Expressive array utilities with an optional C backend.
|
|
5
|
+
Author: OpenAI Codex
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: array,utilities,c-extension,numpy
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: C
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Topic :: Utilities
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Provides-Extra: numpy
|
|
23
|
+
Requires-Dist: numpy>=1.24; extra == "numpy"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# smartarr
|
|
27
|
+
|
|
28
|
+
`smartarr` is an expressive array utility layer for Python with a clean `smart(arr)` API and an optional C backend for fast core operations.
|
|
29
|
+
|
|
30
|
+
## Why it exists
|
|
31
|
+
|
|
32
|
+
The goal is simple:
|
|
33
|
+
|
|
34
|
+
- one readable interface for lists, tuples, and NumPy arrays
|
|
35
|
+
- fast common operations when the C extension is available
|
|
36
|
+
- chainable transformations that still feel like Python
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from smartarr import smart
|
|
40
|
+
|
|
41
|
+
value = smart([1, 2, 3, 4, 5]).rotate(2).reverse().middle()
|
|
42
|
+
print(value) # 1
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
Local install from this project:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
python -m pip install .
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Editable install for development:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
python -m pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Optional NumPy support:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
python -m pip install ".[numpy]"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If a compiler is available, `smartarr` builds its C extension automatically. If not, installation still succeeds and falls back to the pure Python backend.
|
|
66
|
+
|
|
67
|
+
## Quick start
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from smartarr import smart
|
|
71
|
+
|
|
72
|
+
arr = smart([1, 2, 3, 4])
|
|
73
|
+
|
|
74
|
+
print(arr.first()) # 1
|
|
75
|
+
print(arr.last()) # 4
|
|
76
|
+
print(arr.middle()) # 3
|
|
77
|
+
print(arr.middle(mode="left")) # 2
|
|
78
|
+
print(arr.middle(mode="avg")) # 2.5
|
|
79
|
+
print(arr.rotate(1).to_list()) # [4, 1, 2, 3]
|
|
80
|
+
print(arr.reverse().to_list()) # [4, 3, 2, 1]
|
|
81
|
+
print(arr.chunk(2).to_list()) # [[1, 2], [3, 4]]
|
|
82
|
+
print(arr.window(2).to_list()) # [[1, 2], [2, 3], [3, 4]]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Design notes
|
|
86
|
+
|
|
87
|
+
- `middle()` defaults to the right-middle element for even-length arrays, matching `arr[len(arr) // 2]`.
|
|
88
|
+
- Structural methods return a new `SmartArray`, so chaining works naturally.
|
|
89
|
+
- Terminal methods return a final value, such as an element, a number, or a dictionary.
|
|
90
|
+
- Flat transformations preserve the original adapter where practical. Shape-changing operations return list-shaped data by default.
|
|
91
|
+
|
|
92
|
+
## Supported input types
|
|
93
|
+
|
|
94
|
+
- `list`
|
|
95
|
+
- `tuple`
|
|
96
|
+
- NumPy `ndarray` when NumPy is installed
|
|
97
|
+
- general iterables such as `range`
|
|
98
|
+
|
|
99
|
+
## Current feature coverage
|
|
100
|
+
|
|
101
|
+
### V1
|
|
102
|
+
|
|
103
|
+
- `first`
|
|
104
|
+
- `last`
|
|
105
|
+
- `middle`
|
|
106
|
+
- `rotate`
|
|
107
|
+
- `reverse`
|
|
108
|
+
- `len`
|
|
109
|
+
- `is_empty`
|
|
110
|
+
|
|
111
|
+
### V2
|
|
112
|
+
|
|
113
|
+
- `chunk`
|
|
114
|
+
- `window`
|
|
115
|
+
- `random`
|
|
116
|
+
- `find`
|
|
117
|
+
- `count`
|
|
118
|
+
- `contains`
|
|
119
|
+
- `is_sorted`
|
|
120
|
+
- `sorted`
|
|
121
|
+
|
|
122
|
+
### V3
|
|
123
|
+
|
|
124
|
+
- `map`
|
|
125
|
+
- `filter`
|
|
126
|
+
- `reduce`
|
|
127
|
+
- `sum`
|
|
128
|
+
- `mean`
|
|
129
|
+
- `median`
|
|
130
|
+
- `min`
|
|
131
|
+
- `max`
|
|
132
|
+
- `peaks`
|
|
133
|
+
- `unique`
|
|
134
|
+
- `duplicates`
|
|
135
|
+
- `frequency`
|
|
136
|
+
- `flatten`
|
|
137
|
+
- `reshape`
|
|
138
|
+
|
|
139
|
+
## Development
|
|
140
|
+
|
|
141
|
+
Run tests:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
python -m unittest discover -s tests -v
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
MIT
|
smartarr-0.1.0/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# smartarr
|
|
2
|
+
|
|
3
|
+
`smartarr` is an expressive array utility layer for Python with a clean `smart(arr)` API and an optional C backend for fast core operations.
|
|
4
|
+
|
|
5
|
+
## Why it exists
|
|
6
|
+
|
|
7
|
+
The goal is simple:
|
|
8
|
+
|
|
9
|
+
- one readable interface for lists, tuples, and NumPy arrays
|
|
10
|
+
- fast common operations when the C extension is available
|
|
11
|
+
- chainable transformations that still feel like Python
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from smartarr import smart
|
|
15
|
+
|
|
16
|
+
value = smart([1, 2, 3, 4, 5]).rotate(2).reverse().middle()
|
|
17
|
+
print(value) # 1
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
Local install from this project:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
python -m pip install .
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Editable install for development:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
python -m pip install -e .
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Optional NumPy support:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python -m pip install ".[numpy]"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
If a compiler is available, `smartarr` builds its C extension automatically. If not, installation still succeeds and falls back to the pure Python backend.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
from smartarr import smart
|
|
46
|
+
|
|
47
|
+
arr = smart([1, 2, 3, 4])
|
|
48
|
+
|
|
49
|
+
print(arr.first()) # 1
|
|
50
|
+
print(arr.last()) # 4
|
|
51
|
+
print(arr.middle()) # 3
|
|
52
|
+
print(arr.middle(mode="left")) # 2
|
|
53
|
+
print(arr.middle(mode="avg")) # 2.5
|
|
54
|
+
print(arr.rotate(1).to_list()) # [4, 1, 2, 3]
|
|
55
|
+
print(arr.reverse().to_list()) # [4, 3, 2, 1]
|
|
56
|
+
print(arr.chunk(2).to_list()) # [[1, 2], [3, 4]]
|
|
57
|
+
print(arr.window(2).to_list()) # [[1, 2], [2, 3], [3, 4]]
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Design notes
|
|
61
|
+
|
|
62
|
+
- `middle()` defaults to the right-middle element for even-length arrays, matching `arr[len(arr) // 2]`.
|
|
63
|
+
- Structural methods return a new `SmartArray`, so chaining works naturally.
|
|
64
|
+
- Terminal methods return a final value, such as an element, a number, or a dictionary.
|
|
65
|
+
- Flat transformations preserve the original adapter where practical. Shape-changing operations return list-shaped data by default.
|
|
66
|
+
|
|
67
|
+
## Supported input types
|
|
68
|
+
|
|
69
|
+
- `list`
|
|
70
|
+
- `tuple`
|
|
71
|
+
- NumPy `ndarray` when NumPy is installed
|
|
72
|
+
- general iterables such as `range`
|
|
73
|
+
|
|
74
|
+
## Current feature coverage
|
|
75
|
+
|
|
76
|
+
### V1
|
|
77
|
+
|
|
78
|
+
- `first`
|
|
79
|
+
- `last`
|
|
80
|
+
- `middle`
|
|
81
|
+
- `rotate`
|
|
82
|
+
- `reverse`
|
|
83
|
+
- `len`
|
|
84
|
+
- `is_empty`
|
|
85
|
+
|
|
86
|
+
### V2
|
|
87
|
+
|
|
88
|
+
- `chunk`
|
|
89
|
+
- `window`
|
|
90
|
+
- `random`
|
|
91
|
+
- `find`
|
|
92
|
+
- `count`
|
|
93
|
+
- `contains`
|
|
94
|
+
- `is_sorted`
|
|
95
|
+
- `sorted`
|
|
96
|
+
|
|
97
|
+
### V3
|
|
98
|
+
|
|
99
|
+
- `map`
|
|
100
|
+
- `filter`
|
|
101
|
+
- `reduce`
|
|
102
|
+
- `sum`
|
|
103
|
+
- `mean`
|
|
104
|
+
- `median`
|
|
105
|
+
- `min`
|
|
106
|
+
- `max`
|
|
107
|
+
- `peaks`
|
|
108
|
+
- `unique`
|
|
109
|
+
- `duplicates`
|
|
110
|
+
- `frequency`
|
|
111
|
+
- `flatten`
|
|
112
|
+
- `reshape`
|
|
113
|
+
|
|
114
|
+
## Development
|
|
115
|
+
|
|
116
|
+
Run tests:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python -m unittest discover -s tests -v
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "smartarr"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Expressive array utilities with an optional C backend."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "OpenAI Codex" }
|
|
14
|
+
]
|
|
15
|
+
keywords = ["array", "utilities", "c-extension", "numpy"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"Programming Language :: Python :: 3",
|
|
20
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
21
|
+
"Programming Language :: Python :: 3.9",
|
|
22
|
+
"Programming Language :: Python :: 3.10",
|
|
23
|
+
"Programming Language :: Python :: 3.11",
|
|
24
|
+
"Programming Language :: Python :: 3.12",
|
|
25
|
+
"Programming Language :: C",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
"Topic :: Utilities"
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.optional-dependencies]
|
|
31
|
+
numpy = ["numpy>=1.24"]
|
|
32
|
+
|
|
33
|
+
[tool.setuptools]
|
|
34
|
+
package-dir = {"" = "src"}
|
|
35
|
+
|
|
36
|
+
[tool.setuptools.packages.find]
|
|
37
|
+
where = ["src"]
|
smartarr-0.1.0/setup.cfg
ADDED
smartarr-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from distutils.errors import CCompilerError, DistutilsExecError, DistutilsPlatformError
|
|
4
|
+
|
|
5
|
+
from setuptools import Extension, setup
|
|
6
|
+
from setuptools.command.build_ext import build_ext
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class OptionalBuildExt(build_ext):
|
|
10
|
+
"""Allow installation to continue when the optional C build is unavailable."""
|
|
11
|
+
|
|
12
|
+
def run(self) -> None:
|
|
13
|
+
try:
|
|
14
|
+
super().run()
|
|
15
|
+
except (DistutilsPlatformError, DistutilsExecError, CCompilerError, OSError, ValueError) as exc:
|
|
16
|
+
self._announce_skip(exc)
|
|
17
|
+
|
|
18
|
+
def build_extension(self, ext: Extension) -> None:
|
|
19
|
+
try:
|
|
20
|
+
super().build_extension(ext)
|
|
21
|
+
except (DistutilsPlatformError, DistutilsExecError, CCompilerError, OSError, ValueError) as exc:
|
|
22
|
+
self._announce_skip(exc)
|
|
23
|
+
|
|
24
|
+
def _announce_skip(self, exc: BaseException) -> None:
|
|
25
|
+
self.warn(
|
|
26
|
+
f"Skipping optional C extension for smartarr. "
|
|
27
|
+
f"The pure Python backend will be used instead. Reason: {exc}"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
setup(
|
|
32
|
+
ext_modules=[
|
|
33
|
+
Extension(
|
|
34
|
+
"smartarr._smartarr",
|
|
35
|
+
sources=["src/smartarr/_smartarr.c"],
|
|
36
|
+
optional=True,
|
|
37
|
+
)
|
|
38
|
+
],
|
|
39
|
+
cmdclass={"build_ext": OptionalBuildExt},
|
|
40
|
+
)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from . import _pybackend
|
|
4
|
+
|
|
5
|
+
try: # pragma: no cover - depends on build environment
|
|
6
|
+
from . import _smartarr as _cbackend
|
|
7
|
+
except ImportError: # pragma: no cover - exercised when C build is unavailable
|
|
8
|
+
_cbackend = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
BACKEND_NAME = "c" if _cbackend is not None else "python"
|
|
12
|
+
|
|
13
|
+
length = _cbackend.length if _cbackend is not None else _pybackend.length
|
|
14
|
+
is_empty = _cbackend.is_empty if _cbackend is not None else _pybackend.is_empty
|
|
15
|
+
first = _cbackend.first if _cbackend is not None else _pybackend.first
|
|
16
|
+
last = _cbackend.last if _cbackend is not None else _pybackend.last
|
|
17
|
+
middle = _cbackend.middle if _cbackend is not None else _pybackend.middle
|
|
18
|
+
rotate = _cbackend.rotate if _cbackend is not None else _pybackend.rotate
|
|
19
|
+
reverse = _cbackend.reverse if _cbackend is not None else _pybackend.reverse
|
|
20
|
+
find = _cbackend.find if _cbackend is not None else _pybackend.find
|
|
21
|
+
count = _cbackend.count if _cbackend is not None else _pybackend.count
|
|
22
|
+
contains = _cbackend.contains if _cbackend is not None else _pybackend.contains
|
|
23
|
+
chunk = _cbackend.chunk if _cbackend is not None else _pybackend.chunk
|
|
24
|
+
window = _cbackend.window if _cbackend is not None else _pybackend.window
|
|
25
|
+
is_sorted = _cbackend.is_sorted if _cbackend is not None else _pybackend.is_sorted
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def length(values: list[Any]) -> int:
|
|
7
|
+
return len(values)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def is_empty(values: list[Any]) -> bool:
|
|
11
|
+
return len(values) == 0
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def first(values: list[Any]) -> Any:
|
|
15
|
+
if not values:
|
|
16
|
+
raise ValueError("smartarr.first() cannot operate on an empty sequence")
|
|
17
|
+
return values[0]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def last(values: list[Any]) -> Any:
|
|
21
|
+
if not values:
|
|
22
|
+
raise ValueError("smartarr.last() cannot operate on an empty sequence")
|
|
23
|
+
return values[-1]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def middle(values: list[Any], mode: str = "right") -> Any:
|
|
27
|
+
if not values:
|
|
28
|
+
raise ValueError("smartarr.middle() cannot operate on an empty sequence")
|
|
29
|
+
if mode not in {"left", "right", "avg"}:
|
|
30
|
+
raise ValueError("middle mode must be one of: right, left, avg")
|
|
31
|
+
|
|
32
|
+
size = len(values)
|
|
33
|
+
if size % 2 == 1:
|
|
34
|
+
return values[size // 2]
|
|
35
|
+
|
|
36
|
+
if mode == "left":
|
|
37
|
+
return values[(size // 2) - 1]
|
|
38
|
+
if mode == "right":
|
|
39
|
+
return values[size // 2]
|
|
40
|
+
|
|
41
|
+
return (values[(size // 2) - 1] + values[size // 2]) / 2
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def rotate(values: list[Any], steps: int) -> list[Any]:
|
|
45
|
+
if not values:
|
|
46
|
+
return []
|
|
47
|
+
steps = steps % len(values)
|
|
48
|
+
if steps == 0:
|
|
49
|
+
return list(values)
|
|
50
|
+
return list(values[-steps:] + values[:-steps])
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def reverse(values: list[Any]) -> list[Any]:
|
|
54
|
+
return list(reversed(values))
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def find(values: list[Any], needle: Any) -> int:
|
|
58
|
+
for index, item in enumerate(values):
|
|
59
|
+
if item == needle:
|
|
60
|
+
return index
|
|
61
|
+
return -1
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def count(values: list[Any], needle: Any) -> int:
|
|
65
|
+
total = 0
|
|
66
|
+
for item in values:
|
|
67
|
+
if item == needle:
|
|
68
|
+
total += 1
|
|
69
|
+
return total
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def contains(values: list[Any], needle: Any) -> bool:
|
|
73
|
+
return find(values, needle) != -1
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def chunk(values: list[Any], size: int, drop_last: bool = False) -> list[list[Any]]:
|
|
77
|
+
if size <= 0:
|
|
78
|
+
raise ValueError("chunk size must be greater than 0")
|
|
79
|
+
|
|
80
|
+
chunks = [values[index : index + size] for index in range(0, len(values), size)]
|
|
81
|
+
if drop_last and chunks and len(chunks[-1]) < size:
|
|
82
|
+
chunks.pop()
|
|
83
|
+
return chunks
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def window(values: list[Any], size: int, step: int = 1) -> list[list[Any]]:
|
|
87
|
+
if size <= 0:
|
|
88
|
+
raise ValueError("window size must be greater than 0")
|
|
89
|
+
if step <= 0:
|
|
90
|
+
raise ValueError("window step must be greater than 0")
|
|
91
|
+
if size > len(values):
|
|
92
|
+
return []
|
|
93
|
+
|
|
94
|
+
return [
|
|
95
|
+
values[index : index + size]
|
|
96
|
+
for index in range(0, len(values) - size + 1, step)
|
|
97
|
+
]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def is_sorted(values: list[Any], reverse: bool = False) -> bool:
|
|
101
|
+
if len(values) < 2:
|
|
102
|
+
return True
|
|
103
|
+
|
|
104
|
+
if reverse:
|
|
105
|
+
return all(values[index - 1] >= values[index] for index in range(1, len(values)))
|
|
106
|
+
return all(values[index - 1] <= values[index] for index in range(1, len(values)))
|