pythonic-fp-circulararray 6.0.4__py3-none-any.whl → 6.1.1__py3-none-any.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.
- pythonic_fp/circulararray/__init__.py +6 -8
- pythonic_fp/circulararray/auto.py +236 -133
- pythonic_fp/circulararray/auto.pyi +3 -3
- pythonic_fp/circulararray/fixed.py +240 -138
- pythonic_fp/circulararray/fixed.pyi +5 -5
- {pythonic_fp_circulararray-6.0.4.dist-info → pythonic_fp_circulararray-6.1.1.dist-info}/METADATA +6 -6
- pythonic_fp_circulararray-6.1.1.dist-info/RECORD +11 -0
- pythonic_fp_circulararray-6.0.4.dist-info/RECORD +0 -11
- {pythonic_fp_circulararray-6.0.4.dist-info → pythonic_fp_circulararray-6.1.1.dist-info}/WHEEL +0 -0
- {pythonic_fp_circulararray-6.0.4.dist-info → pythonic_fp_circulararray-6.1.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,19 +14,17 @@
|
|
|
14
14
|
|
|
15
15
|
"""
|
|
16
16
|
Circular Array
|
|
17
|
-
|
|
17
|
+
==============
|
|
18
18
|
|
|
19
|
-
.. admonition:: Stateful circular array data structures
|
|
19
|
+
.. admonition:: Stateful circular array data structures
|
|
20
20
|
|
|
21
|
-
- O(1) pops and pushes either
|
|
21
|
+
- O(1) pops and pushes on either side
|
|
22
22
|
- O(1) size determination
|
|
23
23
|
- O(1) indexing
|
|
24
|
-
-
|
|
24
|
+
- two types of circular arrays
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- Class constructors ``CA`` and ``CAF`` take an optional iterator to populate circular array.
|
|
29
|
-
- Factory Functions ``ca`` and ``caf`` take a variable number of parameters to populate circular array.
|
|
26
|
+
- fixed capacity: ``CAF``
|
|
27
|
+
- variable capacity: ``CA``
|
|
30
28
|
|
|
31
29
|
"""
|
|
32
30
|
|
|
@@ -12,20 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
"""
|
|
16
|
-
.. admonition:: Variable storage capacity circular array CA
|
|
17
|
-
|
|
18
|
-
- O(1) pops either end
|
|
19
|
-
- O(1) amortized pushes either end
|
|
20
|
-
- O(1) indexing, fully supports slicing
|
|
21
|
-
- auto-resizing more storage capacity when necessary, manually compatible
|
|
22
|
-
- iterable, safely mutates while iterators iterating over previous state
|
|
23
|
-
- comparisons compare identity before equality, like builtins
|
|
24
|
-
- in boolean context, falsy when empty, otherwise truthy
|
|
25
|
-
- function ``ca`` produces auto-resizing circular array from arguments
|
|
26
|
-
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
15
|
from collections.abc import Callable, Iterable, Iterator
|
|
30
16
|
from typing import cast, Final, overload
|
|
31
17
|
from pythonic_fp.gadgets.sentinels.novalue import NoValue
|
|
@@ -36,17 +22,37 @@ nada: Final[NoValue] = NoValue()
|
|
|
36
22
|
|
|
37
23
|
|
|
38
24
|
class CA[X]:
|
|
25
|
+
"""
|
|
26
|
+
.. admonition:: Auto resizing circular array CA
|
|
27
|
+
|
|
28
|
+
- O(1) pops either end
|
|
29
|
+
- O(1) amortized pushes either end
|
|
30
|
+
- O(1) indexing, fully supports slicing
|
|
31
|
+
- auto-resizing more storage capacity when necessary,
|
|
32
|
+
manually compatible
|
|
33
|
+
- iterable but not threadsafe
|
|
34
|
+
- comparisons compare identity before equality, like builtins
|
|
35
|
+
- in boolean context, falsy when empty, otherwise truthy
|
|
36
|
+
- function ``ca`` produces auto-resizing circular array
|
|
37
|
+
from arguments
|
|
38
|
+
|
|
39
|
+
"""
|
|
39
40
|
__slots__ = '_xs', '_cnt', '_cap', '_front', '_rear'
|
|
40
41
|
|
|
41
42
|
def __init__(self, *xs: Iterable[X]) -> None:
|
|
42
43
|
"""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
.. admonition:: initializer
|
|
45
|
+
|
|
46
|
+
Populate ``CA`` with an optional iterable
|
|
47
|
+
from front (left) to rear (right).
|
|
48
|
+
|
|
49
|
+
:param xs: Takes 0 or 1 iterable parameters.
|
|
50
|
+
:raises ValueError: When more than one parameter is provided.
|
|
51
|
+
:raises TypeError: When passed a non-iterable parameter.
|
|
46
52
|
|
|
47
53
|
"""
|
|
48
54
|
if (size := len(xs)) > 1:
|
|
49
|
-
msg = f'CA expects at most 1
|
|
55
|
+
msg = f'CA expects at most 1 iterable, got {size}'
|
|
50
56
|
raise ValueError(msg)
|
|
51
57
|
if size:
|
|
52
58
|
values: list[X | NoValue] = list(cast(Iterable[X | NoValue], xs[0]))
|
|
@@ -139,7 +145,96 @@ class CA[X]:
|
|
|
139
145
|
+ [nada],
|
|
140
146
|
)
|
|
141
147
|
|
|
148
|
+
def __bool__(self) -> bool:
|
|
149
|
+
"""
|
|
150
|
+
.. admonition:: bool
|
|
151
|
+
|
|
152
|
+
- falsy when empty
|
|
153
|
+
- truthy when not empty
|
|
154
|
+
|
|
155
|
+
:returns: ``True`` when not empty,
|
|
156
|
+
``False`` otherwise.
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
return self._cnt > 0
|
|
160
|
+
|
|
161
|
+
def __len__(self) -> int:
|
|
162
|
+
"""
|
|
163
|
+
.. admonition:: length
|
|
164
|
+
|
|
165
|
+
Number of items in the ``CA``.
|
|
166
|
+
|
|
167
|
+
:returns: The number of items in the ``CA``.
|
|
168
|
+
|
|
169
|
+
"""
|
|
170
|
+
return self._cnt
|
|
171
|
+
|
|
172
|
+
def __eq__(self, other: object) -> bool:
|
|
173
|
+
"""
|
|
174
|
+
.. admonition:: equality comparison
|
|
175
|
+
|
|
176
|
+
Efficiently compare ``CA`` to another object.
|
|
177
|
+
|
|
178
|
+
:param other: The object to be compared.
|
|
179
|
+
:returns: ``True`` if ``other`` is another ``CA`` whose
|
|
180
|
+
contents compare as equal to the corresponding
|
|
181
|
+
contents of the ``CA``, otherwise ``False``.
|
|
182
|
+
|
|
183
|
+
"""
|
|
184
|
+
if self is other:
|
|
185
|
+
return True
|
|
186
|
+
if not isinstance(other, type(self)):
|
|
187
|
+
return False
|
|
188
|
+
|
|
189
|
+
(
|
|
190
|
+
front1,
|
|
191
|
+
cnt1,
|
|
192
|
+
capacity1,
|
|
193
|
+
front2,
|
|
194
|
+
cnt2,
|
|
195
|
+
capacity2,
|
|
196
|
+
) = (
|
|
197
|
+
self._front,
|
|
198
|
+
self._cnt,
|
|
199
|
+
self._cap,
|
|
200
|
+
other._front,
|
|
201
|
+
other._cnt,
|
|
202
|
+
other._cap,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
if cnt1 != cnt2:
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
for nn in range(cnt1):
|
|
209
|
+
if (
|
|
210
|
+
self._xs[(front1 + nn) % capacity1]
|
|
211
|
+
is other._xs[(front2 + nn) % capacity2]
|
|
212
|
+
):
|
|
213
|
+
continue
|
|
214
|
+
if (
|
|
215
|
+
self._xs[(front1 + nn) % capacity1]
|
|
216
|
+
!= other._xs[(front2 + nn) % capacity2]
|
|
217
|
+
):
|
|
218
|
+
return False
|
|
219
|
+
return True
|
|
220
|
+
|
|
142
221
|
def __iter__(self) -> Iterator[X]:
|
|
222
|
+
"""
|
|
223
|
+
.. admonition:: iterate
|
|
224
|
+
|
|
225
|
+
Iterates circular array, front (left) to rear (right).
|
|
226
|
+
|
|
227
|
+
.. warning
|
|
228
|
+
|
|
229
|
+
Not thread safe, especially for long living iterators.
|
|
230
|
+
|
|
231
|
+
.. tip::
|
|
232
|
+
|
|
233
|
+
Cache contents to make more thread tolerant. Put
|
|
234
|
+
a lock around circular array during caching process
|
|
235
|
+
to make threadsafe.
|
|
236
|
+
|
|
237
|
+
"""
|
|
143
238
|
if self._cnt > 0:
|
|
144
239
|
(
|
|
145
240
|
capacity,
|
|
@@ -159,6 +254,22 @@ class CA[X]:
|
|
|
159
254
|
yield cast(X, current_state[position])
|
|
160
255
|
|
|
161
256
|
def __reversed__(self) -> Iterator[X]:
|
|
257
|
+
"""
|
|
258
|
+
.. admonition:: reverse iterate
|
|
259
|
+
|
|
260
|
+
Iterates circular array, rear (right) to front (left).
|
|
261
|
+
|
|
262
|
+
.. warning
|
|
263
|
+
|
|
264
|
+
Not thread safe, especially for long living iterators.
|
|
265
|
+
|
|
266
|
+
.. tip::
|
|
267
|
+
|
|
268
|
+
Cache contents to make more thread tolerant. Put
|
|
269
|
+
a lock around circular array during caching process
|
|
270
|
+
to make threadsafe.
|
|
271
|
+
|
|
272
|
+
"""
|
|
162
273
|
if self._cnt > 0:
|
|
163
274
|
(
|
|
164
275
|
capacity,
|
|
@@ -177,32 +288,19 @@ class CA[X]:
|
|
|
177
288
|
position = (position - 1) % capacity
|
|
178
289
|
yield cast(X, current_state[position])
|
|
179
290
|
|
|
180
|
-
def __repr__(self) -> str:
|
|
181
|
-
"""
|
|
182
|
-
:returns: String of the form ``ca(x1, x2, ..., xn)``.
|
|
183
|
-
|
|
184
|
-
"""
|
|
185
|
-
return 'ca(' + ', '.join(map(repr, self)) + ')'
|
|
186
|
-
|
|
187
|
-
def __str__(self) -> str:
|
|
188
|
-
"""
|
|
189
|
-
:returns: String of the form ``(|x1, x2, ..., xn|)``.
|
|
190
|
-
|
|
191
|
-
"""
|
|
192
|
-
return '(|' + ', '.join(map(str, self)) + '|)'
|
|
193
|
-
|
|
194
|
-
def __bool__(self) -> bool:
|
|
195
|
-
return self._cnt > 0
|
|
196
|
-
|
|
197
|
-
def __len__(self) -> int:
|
|
198
|
-
return self._cnt
|
|
199
|
-
|
|
200
291
|
@overload
|
|
201
292
|
def __getitem__(self, idx: int) -> X: ...
|
|
202
293
|
@overload
|
|
203
294
|
def __getitem__(self, idx: slice) -> 'CA[X]': ...
|
|
204
295
|
|
|
205
296
|
def __getitem__(self, idx: int | slice) -> X | 'CA[X]':
|
|
297
|
+
"""
|
|
298
|
+
.. admonition:: getitem
|
|
299
|
+
|
|
300
|
+
Auto resizing circular arrays are fully indexable
|
|
301
|
+
and sliceable.
|
|
302
|
+
|
|
303
|
+
"""
|
|
206
304
|
if isinstance(idx, slice):
|
|
207
305
|
return CA(list(self)[idx])
|
|
208
306
|
|
|
@@ -228,6 +326,13 @@ class CA[X]:
|
|
|
228
326
|
def __setitem__(self, idx: slice, vals: Iterable[X]) -> None: ...
|
|
229
327
|
|
|
230
328
|
def __setitem__(self, idx: int | slice, vals: X | Iterable[X]) -> None:
|
|
329
|
+
"""
|
|
330
|
+
.. admonition:: setitem
|
|
331
|
+
|
|
332
|
+
Auto resizing circular arrays are fully indexable
|
|
333
|
+
and sliceable.
|
|
334
|
+
|
|
335
|
+
"""
|
|
231
336
|
if isinstance(idx, slice):
|
|
232
337
|
if isinstance(vals, Iterable):
|
|
233
338
|
item_list = list(self)
|
|
@@ -271,6 +376,13 @@ class CA[X]:
|
|
|
271
376
|
def __delitem__(self, idx: slice) -> None: ...
|
|
272
377
|
|
|
273
378
|
def __delitem__(self, idx: int | slice) -> None:
|
|
379
|
+
"""
|
|
380
|
+
.. admonition:: delitem
|
|
381
|
+
|
|
382
|
+
Auto resizing circular arrays are fully indexable
|
|
383
|
+
and sliceable.
|
|
384
|
+
|
|
385
|
+
"""
|
|
274
386
|
item_list = list(self)
|
|
275
387
|
del item_list[idx]
|
|
276
388
|
_ca = CA(item_list)
|
|
@@ -289,62 +401,42 @@ class CA[X]:
|
|
|
289
401
|
)
|
|
290
402
|
del _ca
|
|
291
403
|
|
|
292
|
-
def
|
|
404
|
+
def __repr__(self) -> str:
|
|
293
405
|
"""
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
406
|
+
.. admonition:: repr string
|
|
407
|
+
|
|
408
|
+
Construct string 'CA(x₁, x₂, … xₙ)' where
|
|
409
|
+
x₁, x₂, … xₙ are the contents displayed with ``repr()``.
|
|
410
|
+
|
|
411
|
+
:returns: A string to reproduce the ``CA``.
|
|
298
412
|
|
|
299
413
|
"""
|
|
300
|
-
|
|
301
|
-
return True
|
|
302
|
-
if not isinstance(other, type(self)):
|
|
303
|
-
return False
|
|
414
|
+
return 'ca(' + ', '.join(map(repr, self)) + ')'
|
|
304
415
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
capacity1,
|
|
309
|
-
front2,
|
|
310
|
-
cnt2,
|
|
311
|
-
capacity2,
|
|
312
|
-
) = (
|
|
313
|
-
self._front,
|
|
314
|
-
self._cnt,
|
|
315
|
-
self._cap,
|
|
316
|
-
other._front,
|
|
317
|
-
other._cnt,
|
|
318
|
-
other._cap,
|
|
319
|
-
)
|
|
416
|
+
def __str__(self) -> str:
|
|
417
|
+
r"""
|
|
418
|
+
.. admonition:: user string
|
|
320
419
|
|
|
321
|
-
|
|
322
|
-
|
|
420
|
+
Construct string '(\| x₁, x₂, … xₙ \|)' where
|
|
421
|
+
x₁, x₂, ..., xₙ are the contents displayed with ``str()``.
|
|
323
422
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
):
|
|
329
|
-
continue
|
|
330
|
-
if (
|
|
331
|
-
self._xs[(front1 + nn) % capacity1]
|
|
332
|
-
!= other._xs[(front2 + nn) % capacity2]
|
|
333
|
-
):
|
|
334
|
-
return False
|
|
335
|
-
return True
|
|
423
|
+
:returns: A estring meaningful to an end user.
|
|
424
|
+
|
|
425
|
+
"""
|
|
426
|
+
return '(| ' + ', '.join(map(str, self)) + ' |)'
|
|
336
427
|
|
|
337
428
|
def pushl(self, *xs: X) -> None:
|
|
338
429
|
"""
|
|
339
|
-
.. admonition::
|
|
430
|
+
.. admonition:: push left
|
|
340
431
|
|
|
341
432
|
Push items from the left onto the ``CA`` in the
|
|
342
433
|
order they were iterated.
|
|
343
434
|
|
|
344
|
-
|
|
435
|
+
:param xs: Items to be pushed onto the front of the ``CA``
|
|
436
|
+
from the left.
|
|
345
437
|
|
|
346
438
|
"""
|
|
347
|
-
for
|
|
439
|
+
for x in xs:
|
|
348
440
|
if self._cnt == self._cap:
|
|
349
441
|
self._double_storage_capacity()
|
|
350
442
|
(
|
|
@@ -353,18 +445,19 @@ class CA[X]:
|
|
|
353
445
|
self._cnt,
|
|
354
446
|
) = (
|
|
355
447
|
(self._front - 1) % self._cap,
|
|
356
|
-
|
|
448
|
+
x,
|
|
357
449
|
self._cnt + 1,
|
|
358
450
|
)
|
|
359
451
|
|
|
360
452
|
def pushr(self, *xs: X) -> None:
|
|
361
453
|
"""
|
|
362
|
-
.. admonition::
|
|
454
|
+
.. admonition:: push right
|
|
363
455
|
|
|
364
456
|
Push items from the right onto the ``CA`` in the
|
|
365
457
|
order they were iterated.
|
|
366
458
|
|
|
367
|
-
|
|
459
|
+
:param xs: Items to be pushed onto the rear of
|
|
460
|
+
the ``CA`` from the right.
|
|
368
461
|
|
|
369
462
|
"""
|
|
370
463
|
for item in xs:
|
|
@@ -382,17 +475,17 @@ class CA[X]:
|
|
|
382
475
|
|
|
383
476
|
def popl(self) -> X:
|
|
384
477
|
"""
|
|
385
|
-
.. admonition::
|
|
478
|
+
.. admonition:: pop left
|
|
386
479
|
|
|
387
480
|
Pop a single items off the left side of the ``CA``.
|
|
388
481
|
|
|
389
|
-
|
|
390
|
-
|
|
482
|
+
:returns: Item popped from left side (front) of the ``CA``.
|
|
483
|
+
:raises ValueError: When called on an empty ``CA``.
|
|
391
484
|
|
|
392
485
|
"""
|
|
393
486
|
if self._cnt > 1:
|
|
394
487
|
(
|
|
395
|
-
|
|
488
|
+
x,
|
|
396
489
|
self._xs[self._front],
|
|
397
490
|
self._front,
|
|
398
491
|
self._cnt,
|
|
@@ -404,7 +497,7 @@ class CA[X]:
|
|
|
404
497
|
)
|
|
405
498
|
elif self._cnt == 1:
|
|
406
499
|
(
|
|
407
|
-
|
|
500
|
+
x,
|
|
408
501
|
self._xs[self._front],
|
|
409
502
|
self._cnt,
|
|
410
503
|
self._front,
|
|
@@ -419,21 +512,21 @@ class CA[X]:
|
|
|
419
512
|
else:
|
|
420
513
|
msg = 'Method popl called on an empty CA'
|
|
421
514
|
raise ValueError(msg)
|
|
422
|
-
return cast(X,
|
|
515
|
+
return cast(X, x)
|
|
423
516
|
|
|
424
517
|
def popr(self) -> X:
|
|
425
518
|
"""
|
|
426
|
-
.. admonition::
|
|
519
|
+
.. admonition:: pop right
|
|
427
520
|
|
|
428
521
|
Pop a single items off the right side of the ``CA``.
|
|
429
522
|
|
|
430
|
-
|
|
431
|
-
|
|
523
|
+
:returns: Item popped from right side (rear) of the ``CA``.
|
|
524
|
+
:raises ValueError: When called on an empty ``CA``.
|
|
432
525
|
|
|
433
526
|
"""
|
|
434
527
|
if self._cnt > 1:
|
|
435
528
|
(
|
|
436
|
-
|
|
529
|
+
x,
|
|
437
530
|
self._xs[self._rear],
|
|
438
531
|
self._rear,
|
|
439
532
|
self._cnt,
|
|
@@ -445,7 +538,7 @@ class CA[X]:
|
|
|
445
538
|
)
|
|
446
539
|
elif self._cnt == 1:
|
|
447
540
|
(
|
|
448
|
-
|
|
541
|
+
x,
|
|
449
542
|
self._xs[self._front],
|
|
450
543
|
self._cnt,
|
|
451
544
|
self._front,
|
|
@@ -460,18 +553,18 @@ class CA[X]:
|
|
|
460
553
|
else:
|
|
461
554
|
msg = 'Method popr called on an empty CA'
|
|
462
555
|
raise ValueError(msg)
|
|
463
|
-
return cast(X,
|
|
556
|
+
return cast(X, x)
|
|
464
557
|
|
|
465
558
|
def popld(self, default: X) -> X:
|
|
466
559
|
"""
|
|
467
|
-
.. admonition::
|
|
560
|
+
.. admonition:: pop Left with default
|
|
468
561
|
|
|
469
562
|
Pop a single items off the left side of the ``CA``.
|
|
470
563
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
564
|
+
:param default: Default value to return if ``CA`` is empty.
|
|
565
|
+
:returns: Item popped from left side (front) of the ``CA``
|
|
566
|
+
if not empty, otherwise return the provided
|
|
567
|
+
default value.
|
|
475
568
|
|
|
476
569
|
"""
|
|
477
570
|
try:
|
|
@@ -481,14 +574,14 @@ class CA[X]:
|
|
|
481
574
|
|
|
482
575
|
def poprd(self, default: X) -> X:
|
|
483
576
|
"""
|
|
484
|
-
.. admonition::
|
|
577
|
+
.. admonition:: pop Right with default
|
|
485
578
|
|
|
486
579
|
Pop a single items off the right side of the ``CA``.
|
|
487
580
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
581
|
+
:param default: Default value to return if ``CA`` is empty.
|
|
582
|
+
:returns: Item popped from right side (rear) of the ``CA``
|
|
583
|
+
if not empty, otherwise return the provided
|
|
584
|
+
default value.
|
|
492
585
|
|
|
493
586
|
"""
|
|
494
587
|
try:
|
|
@@ -502,21 +595,22 @@ class CA[X]:
|
|
|
502
595
|
|
|
503
596
|
Pop items off the left side of the ``CA``.
|
|
504
597
|
|
|
505
|
-
|
|
506
|
-
|
|
598
|
+
:param maximum: Maximum number of items to pop,
|
|
599
|
+
may pop less if not enough items in ``CA``.
|
|
600
|
+
:returns: A ``tuple`` of the items popped, left to right.
|
|
507
601
|
|
|
508
602
|
"""
|
|
509
|
-
|
|
603
|
+
xs: list[X] = []
|
|
510
604
|
|
|
511
605
|
while maximum > 0:
|
|
512
606
|
try:
|
|
513
|
-
|
|
607
|
+
xs.append(self.popl())
|
|
514
608
|
except ValueError:
|
|
515
609
|
break
|
|
516
610
|
else:
|
|
517
611
|
maximum -= 1
|
|
518
612
|
|
|
519
|
-
return tuple(
|
|
613
|
+
return tuple(xs)
|
|
520
614
|
|
|
521
615
|
def poprt(self, maximum: int) -> tuple[X, ...]:
|
|
522
616
|
"""
|
|
@@ -524,8 +618,9 @@ class CA[X]:
|
|
|
524
618
|
|
|
525
619
|
Pop items off the right side of the ``CA``.
|
|
526
620
|
|
|
527
|
-
|
|
528
|
-
|
|
621
|
+
:param maximum: Maximum number of items to pop,
|
|
622
|
+
may pop less if not enough items in ``CA``.
|
|
623
|
+
:returns: A ``tuple`` of the items popped, right to left.
|
|
529
624
|
|
|
530
625
|
"""
|
|
531
626
|
item_list: list[X] = []
|
|
@@ -545,7 +640,8 @@ class CA[X]:
|
|
|
545
640
|
Rotate contents of ``CA`` to the left putting first
|
|
546
641
|
item onto rear.
|
|
547
642
|
|
|
548
|
-
|
|
643
|
+
:param n: Number of times to shift items left.
|
|
644
|
+
Default 1 time.
|
|
549
645
|
|
|
550
646
|
"""
|
|
551
647
|
if self._cnt < 2:
|
|
@@ -560,7 +656,8 @@ class CA[X]:
|
|
|
560
656
|
Rotate contents of ``CA`` to the right putting last
|
|
561
657
|
item onto front.
|
|
562
658
|
|
|
563
|
-
|
|
659
|
+
:param n: Number of times to shift items right.
|
|
660
|
+
Default 1 time.
|
|
564
661
|
|
|
565
662
|
"""
|
|
566
663
|
if self._cnt < 2:
|
|
@@ -574,8 +671,8 @@ class CA[X]:
|
|
|
574
671
|
|
|
575
672
|
Apply function ``f`` over the circular array's contents.
|
|
576
673
|
|
|
577
|
-
|
|
578
|
-
|
|
674
|
+
:param f: Callable from type ``X`` to type ``Y``.
|
|
675
|
+
:returns: New auto-resizing circular array instance.
|
|
579
676
|
|
|
580
677
|
"""
|
|
581
678
|
return CA(map(f, self))
|
|
@@ -591,10 +688,12 @@ class CA[X]:
|
|
|
591
688
|
|
|
592
689
|
Fold ``CA`` left with a function and optional starting item.
|
|
593
690
|
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
691
|
+
:param f: Folding function, first argument to ``f`` is for
|
|
692
|
+
the accumulator.
|
|
693
|
+
:param start: Optional starting item.
|
|
694
|
+
:returns: Reduced value produced by the left fold.
|
|
695
|
+
:raises ValueError: When circular array empty and ``start``
|
|
696
|
+
not given.
|
|
598
697
|
|
|
599
698
|
"""
|
|
600
699
|
if self._cnt == 0:
|
|
@@ -610,8 +709,8 @@ class CA[X]:
|
|
|
610
709
|
return acc
|
|
611
710
|
|
|
612
711
|
acc = cast(L, start)
|
|
613
|
-
for
|
|
614
|
-
acc = f(acc,
|
|
712
|
+
for x in self:
|
|
713
|
+
acc = f(acc, x)
|
|
615
714
|
return acc
|
|
616
715
|
|
|
617
716
|
@overload
|
|
@@ -625,10 +724,12 @@ class CA[X]:
|
|
|
625
724
|
|
|
626
725
|
Fold ``CA`` right with a function and optional starting item.
|
|
627
726
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
727
|
+
:param f: Folding function, second argument to ``f`` is for
|
|
728
|
+
the accumulator.
|
|
729
|
+
:param start: Optional starting item.
|
|
730
|
+
:returns: Reduced value produced by the right fold.
|
|
731
|
+
:raises ValueError: When circular array empty and ``start``
|
|
732
|
+
not given.
|
|
632
733
|
|
|
633
734
|
"""
|
|
634
735
|
if self._cnt == 0:
|
|
@@ -644,8 +745,8 @@ class CA[X]:
|
|
|
644
745
|
return acc
|
|
645
746
|
|
|
646
747
|
acc = cast(R, start)
|
|
647
|
-
for
|
|
648
|
-
acc = f(
|
|
748
|
+
for x in reversed(self):
|
|
749
|
+
acc = f(x, acc)
|
|
649
750
|
return acc
|
|
650
751
|
|
|
651
752
|
def capacity(self) -> int:
|
|
@@ -654,7 +755,7 @@ class CA[X]:
|
|
|
654
755
|
|
|
655
756
|
Get the current storage capacity of the circular array.
|
|
656
757
|
|
|
657
|
-
|
|
758
|
+
:returns: Current storage capacity.
|
|
658
759
|
|
|
659
760
|
"""
|
|
660
761
|
return self._cap
|
|
@@ -684,7 +785,7 @@ class CA[X]:
|
|
|
684
785
|
|
|
685
786
|
Find fraction of the storage capacity which is filled.
|
|
686
787
|
|
|
687
|
-
|
|
788
|
+
:returns: The ratio count/capacity.
|
|
688
789
|
|
|
689
790
|
"""
|
|
690
791
|
return self._cnt / self._cap
|
|
@@ -697,7 +798,8 @@ class CA[X]:
|
|
|
697
798
|
minimum storage capacity. To just compact the circular
|
|
698
799
|
array, do not provide ``minimum_capacity``.
|
|
699
800
|
|
|
700
|
-
:param minimum_capacity: Minimum storage capacity to compact
|
|
801
|
+
:param minimum_capacity: Minimum storage capacity to compact
|
|
802
|
+
the circular array.
|
|
701
803
|
|
|
702
804
|
"""
|
|
703
805
|
self._compact_storage_capacity()
|
|
@@ -717,10 +819,11 @@ def ca[T](*ts: T) -> CA[T]:
|
|
|
717
819
|
"""
|
|
718
820
|
.. admonition:: Circular array factory function
|
|
719
821
|
|
|
720
|
-
Produce a circular array from
|
|
822
|
+
Produce a auto resizing circular array from
|
|
823
|
+
a variable number of arguments.
|
|
721
824
|
|
|
722
|
-
|
|
723
|
-
|
|
825
|
+
:param ts: Initial items for a new auto-resizing circular array.
|
|
826
|
+
:returns: New variable storage capacity circular array.
|
|
724
827
|
|
|
725
828
|
"""
|
|
726
829
|
return CA(ts)
|
|
@@ -5,10 +5,11 @@ __all__ = ['CA', 'ca']
|
|
|
5
5
|
|
|
6
6
|
class CA[X]:
|
|
7
7
|
def __init__(self, *xs: Iterable[X]) -> None: ...
|
|
8
|
-
def __iter__(self) -> Iterator[X]: ...
|
|
9
|
-
def __reversed__(self) -> Iterator[X]: ...
|
|
10
8
|
def __bool__(self) -> bool: ...
|
|
11
9
|
def __len__(self) -> int: ...
|
|
10
|
+
def __eq__(self, other: object) -> bool: ...
|
|
11
|
+
def __iter__(self) -> Iterator[X]: ...
|
|
12
|
+
def __reversed__(self) -> Iterator[X]: ...
|
|
12
13
|
@overload
|
|
13
14
|
def __getitem__(self, idx: int) -> X: ...
|
|
14
15
|
@overload
|
|
@@ -21,7 +22,6 @@ class CA[X]:
|
|
|
21
22
|
def __delitem__(self, idx: int) -> None: ...
|
|
22
23
|
@overload
|
|
23
24
|
def __delitem__(self, idx: slice) -> None: ...
|
|
24
|
-
def __eq__(self, other: object) -> bool: ...
|
|
25
25
|
def pushl(self, *xs: X) -> None: ...
|
|
26
26
|
def pushr(self, *xs: X) -> None: ...
|
|
27
27
|
def popl(self) -> X: ...
|