pythonstl 0.1.4__cp311-cp311-win_amd64.whl
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.
- pythonstl/__init__.py +64 -0
- pythonstl/_rust.cp311-win_amd64.pyd +0 -0
- pythonstl/core/__init__.py +32 -0
- pythonstl/core/base.py +51 -0
- pythonstl/core/exceptions.py +57 -0
- pythonstl/core/iterator.py +187 -0
- pythonstl/facade/__init__.py +10 -0
- pythonstl/facade/algorithms.py +331 -0
- pythonstl/facade/map.py +298 -0
- pythonstl/facade/priority_queue.py +228 -0
- pythonstl/facade/queue.py +234 -0
- pythonstl/facade/set.py +271 -0
- pythonstl/facade/stack.py +217 -0
- pythonstl/facade/vector.py +406 -0
- pythonstl/implementations/__init__.py +3 -0
- pythonstl/implementations/associative/__init__.py +6 -0
- pythonstl/implementations/associative/_map_impl.py +164 -0
- pythonstl/implementations/associative/_set_impl.py +138 -0
- pythonstl/implementations/heaps/__init__.py +5 -0
- pythonstl/implementations/heaps/_priority_queue_impl.py +118 -0
- pythonstl/implementations/linear/__init__.py +7 -0
- pythonstl/implementations/linear/_queue_impl.py +117 -0
- pythonstl/implementations/linear/_stack_impl.py +99 -0
- pythonstl/implementations/linear/_vector_impl.py +251 -0
- pythonstl-0.1.4.dist-info/METADATA +449 -0
- pythonstl-0.1.4.dist-info/RECORD +29 -0
- pythonstl-0.1.4.dist-info/WHEEL +4 -0
- pythonstl-0.1.4.dist-info/licenses/LICENSE +21 -0
- pythonstl-0.1.4.dist-info/sboms/pythonstl.cyclonedx.json +1051 -0
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
"""
|
|
2
|
+
C++ STL Algorithms Suite.
|
|
3
|
+
|
|
4
|
+
This module provides replicas of standard C++ algorithms from <algorithm>
|
|
5
|
+
with dynamic Rust backend loading and in-place list mutation.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Callable, Any
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
from pythonstl._rust import next_permutation as _rust_next_permutation
|
|
12
|
+
from pythonstl._rust import prev_permutation as _rust_prev_permutation
|
|
13
|
+
from pythonstl._rust import nth_element as _rust_nth_element
|
|
14
|
+
from pythonstl._rust import partition as _rust_partition
|
|
15
|
+
from pythonstl._rust import lower_bound as _rust_lower_bound
|
|
16
|
+
from pythonstl._rust import upper_bound as _rust_upper_bound
|
|
17
|
+
from pythonstl._rust import binary_search as _rust_binary_search
|
|
18
|
+
from pythonstl._rust import equal_range as _rust_equal_range
|
|
19
|
+
RUST_AVAILABLE = True
|
|
20
|
+
except ImportError:
|
|
21
|
+
RUST_AVAILABLE = False
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# ----------------- Pure-Python Fallbacks -----------------
|
|
25
|
+
|
|
26
|
+
def _py_next_permutation(arr: list) -> bool:
|
|
27
|
+
n = len(arr)
|
|
28
|
+
if n <= 1:
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
i = n - 2
|
|
32
|
+
while i >= 0 and arr[i] >= arr[i + 1]:
|
|
33
|
+
i -= 1
|
|
34
|
+
|
|
35
|
+
if i < 0:
|
|
36
|
+
arr.reverse()
|
|
37
|
+
return False
|
|
38
|
+
|
|
39
|
+
j = n - 1
|
|
40
|
+
while arr[j] <= arr[i]:
|
|
41
|
+
j -= 1
|
|
42
|
+
|
|
43
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
44
|
+
arr[i + 1:] = reversed(arr[i + 1:])
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _py_prev_permutation(arr: list) -> bool:
|
|
49
|
+
n = len(arr)
|
|
50
|
+
if n <= 1:
|
|
51
|
+
return False
|
|
52
|
+
|
|
53
|
+
i = n - 2
|
|
54
|
+
while i >= 0 and arr[i] <= arr[i + 1]:
|
|
55
|
+
i -= 1
|
|
56
|
+
|
|
57
|
+
if i < 0:
|
|
58
|
+
arr.reverse()
|
|
59
|
+
return False
|
|
60
|
+
|
|
61
|
+
j = n - 1
|
|
62
|
+
while arr[j] >= arr[i]:
|
|
63
|
+
j -= 1
|
|
64
|
+
|
|
65
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
66
|
+
arr[i + 1:] = reversed(arr[i + 1:])
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _py_nth_element(arr: list, nth: int) -> None:
|
|
71
|
+
n = len(arr)
|
|
72
|
+
if nth < 0 or nth >= n:
|
|
73
|
+
return
|
|
74
|
+
|
|
75
|
+
left = 0
|
|
76
|
+
right = n - 1
|
|
77
|
+
while left < right:
|
|
78
|
+
mid = left + (right - left) // 2
|
|
79
|
+
arr[mid], arr[right] = arr[right], arr[mid]
|
|
80
|
+
pivot = arr[right]
|
|
81
|
+
i = left
|
|
82
|
+
for j in range(left, right):
|
|
83
|
+
if arr[j] < pivot:
|
|
84
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
85
|
+
i += 1
|
|
86
|
+
arr[i], arr[right] = arr[right], arr[i]
|
|
87
|
+
|
|
88
|
+
pivot_idx = i
|
|
89
|
+
if pivot_idx == nth:
|
|
90
|
+
return
|
|
91
|
+
elif pivot_idx > nth:
|
|
92
|
+
right = pivot_idx - 1
|
|
93
|
+
else:
|
|
94
|
+
left = pivot_idx + 1
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _py_partition(arr: list, predicate: Callable[[Any], bool]) -> int:
|
|
99
|
+
i = 0
|
|
100
|
+
for j in range(len(arr)):
|
|
101
|
+
if predicate(arr[j]):
|
|
102
|
+
arr[i], arr[j] = arr[j], arr[i]
|
|
103
|
+
i += 1
|
|
104
|
+
return i
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _py_lower_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> int:
|
|
108
|
+
left = 0
|
|
109
|
+
right = len(arr)
|
|
110
|
+
while left < right:
|
|
111
|
+
mid = left + (right - left) // 2
|
|
112
|
+
mid_val = arr[mid]
|
|
113
|
+
is_less = comp(mid_val, val) if comp else (mid_val < val)
|
|
114
|
+
if is_less:
|
|
115
|
+
left = mid + 1
|
|
116
|
+
else:
|
|
117
|
+
right = mid
|
|
118
|
+
return left
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _py_upper_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> int:
|
|
122
|
+
left = 0
|
|
123
|
+
right = len(arr)
|
|
124
|
+
while left < right:
|
|
125
|
+
mid = left + (right - left) // 2
|
|
126
|
+
mid_val = arr[mid]
|
|
127
|
+
is_less = comp(val, mid_val) if comp else (val < mid_val)
|
|
128
|
+
if is_less:
|
|
129
|
+
right = mid
|
|
130
|
+
else:
|
|
131
|
+
left = mid + 1
|
|
132
|
+
return left
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def _py_binary_search(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> bool:
|
|
136
|
+
if not arr:
|
|
137
|
+
return False
|
|
138
|
+
idx = _py_lower_bound(arr, val, comp)
|
|
139
|
+
if idx < len(arr):
|
|
140
|
+
elem = arr[idx]
|
|
141
|
+
if comp:
|
|
142
|
+
return not comp(elem, val) and not comp(val, elem)
|
|
143
|
+
return elem == val
|
|
144
|
+
return False
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def _py_equal_range(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None) -> tuple[int, int]:
|
|
148
|
+
return _py_lower_bound(arr, val, comp), _py_upper_bound(arr, val, comp)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
# ----------------- Public API Interfaces -----------------
|
|
152
|
+
|
|
153
|
+
def next_permutation(arr: list, use_rust: bool = True) -> bool:
|
|
154
|
+
"""
|
|
155
|
+
Rearranges elements in-place to the next lexicographically greater permutation.
|
|
156
|
+
|
|
157
|
+
If the next permutation exists, rearranges elements and returns True.
|
|
158
|
+
Otherwise, reverses the array to the smallest ascending order and returns False.
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
arr: The list to modify in-place.
|
|
162
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
True if next permutation exists, False otherwise.
|
|
166
|
+
|
|
167
|
+
Time Complexity:
|
|
168
|
+
O(n) where n is len(arr)
|
|
169
|
+
"""
|
|
170
|
+
if use_rust and RUST_AVAILABLE:
|
|
171
|
+
return _rust_next_permutation(arr)
|
|
172
|
+
return _py_next_permutation(arr)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def prev_permutation(arr: list, use_rust: bool = True) -> bool:
|
|
176
|
+
"""
|
|
177
|
+
Rearranges elements in-place to the next lexicographically smaller permutation.
|
|
178
|
+
|
|
179
|
+
If the previous permutation exists, rearranges elements and returns True.
|
|
180
|
+
Otherwise, reverses the array to the largest descending order and returns False.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
arr: The list to modify in-place.
|
|
184
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
True if prev permutation exists, False otherwise.
|
|
188
|
+
|
|
189
|
+
Time Complexity:
|
|
190
|
+
O(n) where n is len(arr)
|
|
191
|
+
"""
|
|
192
|
+
if use_rust and RUST_AVAILABLE:
|
|
193
|
+
return _rust_prev_permutation(arr)
|
|
194
|
+
return _py_prev_permutation(arr)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def nth_element(arr: list, nth: int, use_rust: bool = True) -> None:
|
|
198
|
+
"""
|
|
199
|
+
Partitions the list in-place so that the element at index `nth` is the one
|
|
200
|
+
that would be there if the list were completely sorted.
|
|
201
|
+
|
|
202
|
+
All elements preceding `nth` are partitioned to be less than or equal to `nth`.
|
|
203
|
+
All elements succeeding `nth` are partitioned to be greater than or equal to `nth`.
|
|
204
|
+
Does not guarantee sorted order of the surrounding elements.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
arr: The list to modify in-place.
|
|
208
|
+
nth: The index that should contain the sorted element.
|
|
209
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
210
|
+
|
|
211
|
+
Time Complexity:
|
|
212
|
+
O(n) average case
|
|
213
|
+
"""
|
|
214
|
+
if use_rust and RUST_AVAILABLE:
|
|
215
|
+
_rust_nth_element(arr, nth)
|
|
216
|
+
else:
|
|
217
|
+
_py_nth_element(arr, nth)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def partition(arr: list, predicate: Callable[[Any], bool], use_rust: bool = True) -> int:
|
|
221
|
+
"""
|
|
222
|
+
Reorders the elements in the list in-place such that all elements for which
|
|
223
|
+
`predicate` returns True precede all elements for which it returns False.
|
|
224
|
+
|
|
225
|
+
Does not guarantee stable relative ordering.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
arr: The list to modify in-place.
|
|
229
|
+
predicate: A callable returning True or False for each element.
|
|
230
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
The boundary index pointing to the first element that returned False.
|
|
234
|
+
|
|
235
|
+
Time Complexity:
|
|
236
|
+
O(n) where n is len(arr)
|
|
237
|
+
"""
|
|
238
|
+
if use_rust and RUST_AVAILABLE:
|
|
239
|
+
return _rust_partition(arr, predicate)
|
|
240
|
+
return _py_partition(arr, predicate)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def lower_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> int:
|
|
244
|
+
"""
|
|
245
|
+
Returns the index of the first element in the range that does not compare less than `val`.
|
|
246
|
+
|
|
247
|
+
Args:
|
|
248
|
+
arr: The sorted list to search.
|
|
249
|
+
val: The value to search for.
|
|
250
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
251
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
The index of the first element that is >= val, or len(arr) if not found.
|
|
255
|
+
|
|
256
|
+
Time Complexity:
|
|
257
|
+
O(log n)
|
|
258
|
+
"""
|
|
259
|
+
if use_rust and RUST_AVAILABLE:
|
|
260
|
+
return _rust_lower_bound(arr, val, comp)
|
|
261
|
+
return _py_lower_bound(arr, val, comp)
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def upper_bound(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> int:
|
|
265
|
+
"""
|
|
266
|
+
Returns the index of the first element in the range that compares greater than `val`.
|
|
267
|
+
|
|
268
|
+
Args:
|
|
269
|
+
arr: The sorted list to search.
|
|
270
|
+
val: The value to search for.
|
|
271
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
272
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
273
|
+
|
|
274
|
+
Returns:
|
|
275
|
+
The index of the first element that is > val, or len(arr) if not found.
|
|
276
|
+
|
|
277
|
+
Time Complexity:
|
|
278
|
+
O(log n)
|
|
279
|
+
"""
|
|
280
|
+
if use_rust and RUST_AVAILABLE:
|
|
281
|
+
return _rust_upper_bound(arr, val, comp)
|
|
282
|
+
return _py_upper_bound(arr, val, comp)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def binary_search(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> bool:
|
|
286
|
+
"""
|
|
287
|
+
Checks if a value is present in the sorted range.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
arr: The sorted list to search.
|
|
291
|
+
val: The value to search for.
|
|
292
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
293
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
294
|
+
|
|
295
|
+
Returns:
|
|
296
|
+
True if the element equivalent to val is found, False otherwise.
|
|
297
|
+
|
|
298
|
+
Time Complexity:
|
|
299
|
+
O(log n)
|
|
300
|
+
"""
|
|
301
|
+
if use_rust and RUST_AVAILABLE:
|
|
302
|
+
return _rust_binary_search(arr, val, comp)
|
|
303
|
+
return _py_binary_search(arr, val, comp)
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
def equal_range(arr: list, val: Any, comp: Callable[[Any, Any], bool] = None, use_rust: bool = True) -> tuple[int, int]:
|
|
307
|
+
"""
|
|
308
|
+
Returns the range of elements equivalent to a given value.
|
|
309
|
+
|
|
310
|
+
Args:
|
|
311
|
+
arr: The sorted list to search.
|
|
312
|
+
val: The value to search for.
|
|
313
|
+
comp: Optional custom binary comparator Callable(a, b) defining custom less-than.
|
|
314
|
+
use_rust: Whether to use the compiled Rust backend (default: True).
|
|
315
|
+
|
|
316
|
+
Returns:
|
|
317
|
+
A tuple (lower_bound_index, upper_bound_index) defining the range of equivalent elements.
|
|
318
|
+
|
|
319
|
+
Time Complexity:
|
|
320
|
+
O(log n)
|
|
321
|
+
"""
|
|
322
|
+
if use_rust and RUST_AVAILABLE:
|
|
323
|
+
return _rust_equal_range(arr, val, comp)
|
|
324
|
+
return _py_equal_range(arr, val, comp)
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
__all__ = [
|
|
328
|
+
'next_permutation', 'prev_permutation', 'nth_element', 'partition',
|
|
329
|
+
'lower_bound', 'upper_bound', 'binary_search', 'equal_range',
|
|
330
|
+
'RUST_AVAILABLE'
|
|
331
|
+
]
|
pythonstl/facade/map.py
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Map facade class.
|
|
3
|
+
|
|
4
|
+
This module provides the public-facing map class that users interact with.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from typing import TypeVar, Iterator as TypingIterator, Tuple
|
|
8
|
+
from copy import deepcopy
|
|
9
|
+
from pythonstl.core.exceptions import KeyNotFoundError
|
|
10
|
+
from pythonstl.implementations.associative._map_impl import _MapImpl
|
|
11
|
+
from pythonstl.core.iterator import MapIterator
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from pythonstl._rust import RustMap
|
|
15
|
+
RUST_AVAILABLE = True
|
|
16
|
+
except ImportError:
|
|
17
|
+
RUST_AVAILABLE = False
|
|
18
|
+
|
|
19
|
+
K = TypeVar('K')
|
|
20
|
+
V = TypeVar('V')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class stl_map:
|
|
24
|
+
"""
|
|
25
|
+
A map data structure following C++ STL semantics.
|
|
26
|
+
|
|
27
|
+
This is an associative container that stores key-value pairs.
|
|
28
|
+
Named 'stl_map' to avoid potential conflicts.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
>>> from pythonstl import stl_map
|
|
32
|
+
>>> m = stl_map()
|
|
33
|
+
>>> m.insert("key1", 100)
|
|
34
|
+
>>> m.insert("key2", 200)
|
|
35
|
+
>>> m.at("key1")
|
|
36
|
+
100
|
|
37
|
+
>>> "key1" in m
|
|
38
|
+
True
|
|
39
|
+
>>> len(m)
|
|
40
|
+
2
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, use_rust: bool = True) -> None:
|
|
44
|
+
"""
|
|
45
|
+
Initialize an empty map.
|
|
46
|
+
|
|
47
|
+
Time Complexity:
|
|
48
|
+
O(1)
|
|
49
|
+
"""
|
|
50
|
+
if use_rust and RUST_AVAILABLE:
|
|
51
|
+
self._impl = RustMap()
|
|
52
|
+
self._is_rust = True
|
|
53
|
+
else:
|
|
54
|
+
self._impl = _MapImpl()
|
|
55
|
+
self._is_rust = False
|
|
56
|
+
|
|
57
|
+
def insert(self, key: K, value: V) -> None:
|
|
58
|
+
"""
|
|
59
|
+
Insert a key-value pair into the map.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
key: The key to insert.
|
|
63
|
+
value: The value associated with the key.
|
|
64
|
+
|
|
65
|
+
Note:
|
|
66
|
+
If the key already exists, the value is updated.
|
|
67
|
+
|
|
68
|
+
Time Complexity:
|
|
69
|
+
O(1) average case
|
|
70
|
+
"""
|
|
71
|
+
self._impl.insert(key, value)
|
|
72
|
+
|
|
73
|
+
def erase(self, key: K) -> None:
|
|
74
|
+
"""
|
|
75
|
+
Remove a key-value pair from the map.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
key: The key to remove.
|
|
79
|
+
|
|
80
|
+
Note:
|
|
81
|
+
Does nothing if the key is not present (matches C++ STL behavior).
|
|
82
|
+
|
|
83
|
+
Time Complexity:
|
|
84
|
+
O(1) average case
|
|
85
|
+
"""
|
|
86
|
+
self._impl.erase(key)
|
|
87
|
+
|
|
88
|
+
def find(self, key: K) -> bool:
|
|
89
|
+
"""
|
|
90
|
+
Check if a key exists in the map.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
key: The key to search for.
|
|
94
|
+
|
|
95
|
+
Returns:
|
|
96
|
+
True if the key exists, False otherwise.
|
|
97
|
+
|
|
98
|
+
Time Complexity:
|
|
99
|
+
O(1) average case
|
|
100
|
+
"""
|
|
101
|
+
return self._impl.find(key)
|
|
102
|
+
|
|
103
|
+
def at(self, key: K) -> V:
|
|
104
|
+
"""
|
|
105
|
+
Access the value associated with a key.
|
|
106
|
+
|
|
107
|
+
Args:
|
|
108
|
+
key: The key to access.
|
|
109
|
+
|
|
110
|
+
Returns:
|
|
111
|
+
The value associated with the key.
|
|
112
|
+
|
|
113
|
+
Raises:
|
|
114
|
+
KeyNotFoundError: If the key does not exist.
|
|
115
|
+
|
|
116
|
+
Time Complexity:
|
|
117
|
+
O(1) average case
|
|
118
|
+
"""
|
|
119
|
+
if not self.find(key):
|
|
120
|
+
raise KeyNotFoundError(key)
|
|
121
|
+
if self._is_rust:
|
|
122
|
+
return self._impl.at(key)
|
|
123
|
+
return self._impl.at(key)
|
|
124
|
+
|
|
125
|
+
def empty(self) -> bool:
|
|
126
|
+
"""
|
|
127
|
+
Check if the map is empty.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
True if the map is empty, False otherwise.
|
|
131
|
+
|
|
132
|
+
Time Complexity:
|
|
133
|
+
O(1)
|
|
134
|
+
"""
|
|
135
|
+
return self._impl.empty()
|
|
136
|
+
|
|
137
|
+
def size(self) -> int:
|
|
138
|
+
"""
|
|
139
|
+
Get the number of key-value pairs in the map.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
The number of key-value pairs in the map.
|
|
143
|
+
|
|
144
|
+
Time Complexity:
|
|
145
|
+
O(1)
|
|
146
|
+
"""
|
|
147
|
+
return self._impl.size()
|
|
148
|
+
|
|
149
|
+
def begin(self) -> MapIterator:
|
|
150
|
+
"""
|
|
151
|
+
Get iterator to the beginning of the map.
|
|
152
|
+
|
|
153
|
+
Returns:
|
|
154
|
+
Iterator pointing to the first key-value pair.
|
|
155
|
+
|
|
156
|
+
Time Complexity:
|
|
157
|
+
O(1)
|
|
158
|
+
"""
|
|
159
|
+
if self._is_rust:
|
|
160
|
+
return MapIterator(dict(self._impl.get_data()))
|
|
161
|
+
return self._impl.begin()
|
|
162
|
+
|
|
163
|
+
def end(self) -> MapIterator:
|
|
164
|
+
"""
|
|
165
|
+
Get iterator to the end of the map.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
Iterator pointing past the last key-value pair.
|
|
169
|
+
|
|
170
|
+
Time Complexity:
|
|
171
|
+
O(1)
|
|
172
|
+
"""
|
|
173
|
+
if self._is_rust:
|
|
174
|
+
return MapIterator({})
|
|
175
|
+
return self._impl.end()
|
|
176
|
+
|
|
177
|
+
def copy(self) -> 'stl_map':
|
|
178
|
+
"""
|
|
179
|
+
Create a deep copy of the map.
|
|
180
|
+
|
|
181
|
+
Returns:
|
|
182
|
+
A new map with copied key-value pairs.
|
|
183
|
+
|
|
184
|
+
Time Complexity:
|
|
185
|
+
O(n) where n is the number of key-value pairs
|
|
186
|
+
"""
|
|
187
|
+
new_map = stl_map(use_rust=self._is_rust)
|
|
188
|
+
if self._is_rust:
|
|
189
|
+
new_map._impl.set_data(self._impl.get_data())
|
|
190
|
+
else:
|
|
191
|
+
new_map._impl._data = self._impl._data.copy()
|
|
192
|
+
return new_map
|
|
193
|
+
|
|
194
|
+
# Python magic methods
|
|
195
|
+
|
|
196
|
+
def __len__(self) -> int:
|
|
197
|
+
"""
|
|
198
|
+
Get the number of key-value pairs (Python len() support).
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
The number of key-value pairs in the map.
|
|
202
|
+
"""
|
|
203
|
+
return self.size()
|
|
204
|
+
|
|
205
|
+
def __bool__(self) -> bool:
|
|
206
|
+
"""
|
|
207
|
+
Check if map is non-empty (Python bool() support).
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
True if map is non-empty, False otherwise.
|
|
211
|
+
"""
|
|
212
|
+
return not self.empty()
|
|
213
|
+
|
|
214
|
+
def __contains__(self, key: K) -> bool:
|
|
215
|
+
"""
|
|
216
|
+
Check if key exists in map (Python 'in' operator support).
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
key: The key to search for.
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
True if key exists, False otherwise.
|
|
223
|
+
|
|
224
|
+
Time Complexity:
|
|
225
|
+
O(1) average case
|
|
226
|
+
"""
|
|
227
|
+
return self.find(key)
|
|
228
|
+
|
|
229
|
+
def __repr__(self) -> str:
|
|
230
|
+
"""
|
|
231
|
+
Get string representation of the map.
|
|
232
|
+
|
|
233
|
+
Returns:
|
|
234
|
+
String representation showing all key-value pairs.
|
|
235
|
+
"""
|
|
236
|
+
pairs = [f"{k}: {v}" for k, v in self]
|
|
237
|
+
return f"stl_map({{{', '.join(pairs)}}})"
|
|
238
|
+
|
|
239
|
+
def __eq__(self, other: object) -> bool:
|
|
240
|
+
"""
|
|
241
|
+
Check equality with another map.
|
|
242
|
+
|
|
243
|
+
Args:
|
|
244
|
+
other: Another map to compare with.
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
True if maps are equal, False otherwise.
|
|
248
|
+
"""
|
|
249
|
+
if not isinstance(other, stl_map):
|
|
250
|
+
return False
|
|
251
|
+
|
|
252
|
+
self_data = dict(self._impl.get_data()) if self._is_rust else self._impl._data
|
|
253
|
+
other_data = dict(other._impl.get_data()) if other._is_rust else other._impl._data
|
|
254
|
+
return self_data == other_data
|
|
255
|
+
|
|
256
|
+
def __iter__(self) -> TypingIterator[Tuple[K, V]]:
|
|
257
|
+
"""
|
|
258
|
+
Get Python iterator for the map.
|
|
259
|
+
|
|
260
|
+
Returns:
|
|
261
|
+
Iterator over key-value pairs as tuples.
|
|
262
|
+
"""
|
|
263
|
+
if self._is_rust:
|
|
264
|
+
return iter(self._impl.get_data())
|
|
265
|
+
return iter(self._impl.get_data().items())
|
|
266
|
+
|
|
267
|
+
def __copy__(self) -> 'stl_map':
|
|
268
|
+
"""
|
|
269
|
+
Support for copy.copy().
|
|
270
|
+
|
|
271
|
+
Returns:
|
|
272
|
+
A shallow copy of the map.
|
|
273
|
+
"""
|
|
274
|
+
return self.copy()
|
|
275
|
+
|
|
276
|
+
def __deepcopy__(self, memo) -> 'stl_map':
|
|
277
|
+
"""
|
|
278
|
+
Support for copy.deepcopy().
|
|
279
|
+
|
|
280
|
+
Args:
|
|
281
|
+
memo: Memoization dictionary for deepcopy.
|
|
282
|
+
|
|
283
|
+
Returns:
|
|
284
|
+
A deep copy of the map.
|
|
285
|
+
"""
|
|
286
|
+
new_map = stl_map(use_rust=self._is_rust)
|
|
287
|
+
if self._is_rust:
|
|
288
|
+
new_pairs = []
|
|
289
|
+
for k, v in self._impl.get_data():
|
|
290
|
+
new_pairs.append((deepcopy(k, memo), deepcopy(v, memo)))
|
|
291
|
+
new_map._impl.set_data(new_pairs)
|
|
292
|
+
else:
|
|
293
|
+
new_map._impl._data = deepcopy(self._impl._data, memo)
|
|
294
|
+
return new_map
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
__all__ = ['stl_map']
|