absfuyu 5.0.1__py3-none-any.whl → 5.2.0__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.
Potentially problematic release.
This version of absfuyu might be problematic. Click here for more details.
- absfuyu/__init__.py +1 -1
- absfuyu/__main__.py +3 -3
- absfuyu/cli/__init__.py +2 -2
- absfuyu/cli/color.py +30 -14
- absfuyu/cli/config_group.py +9 -2
- absfuyu/cli/do_group.py +13 -6
- absfuyu/cli/game_group.py +9 -2
- absfuyu/cli/tool_group.py +15 -9
- absfuyu/config/__init__.py +2 -2
- absfuyu/core/__init__.py +2 -2
- absfuyu/core/baseclass.py +448 -79
- absfuyu/core/baseclass2.py +2 -2
- absfuyu/core/decorator.py +70 -4
- absfuyu/core/docstring.py +43 -25
- absfuyu/core/dummy_cli.py +2 -2
- absfuyu/core/dummy_func.py +15 -4
- absfuyu/dxt/__init__.py +2 -2
- absfuyu/dxt/dictext.py +5 -2
- absfuyu/dxt/dxt_support.py +2 -2
- absfuyu/dxt/intext.py +34 -3
- absfuyu/dxt/listext.py +300 -113
- absfuyu/dxt/strext.py +75 -15
- absfuyu/extra/__init__.py +2 -2
- absfuyu/extra/beautiful.py +2 -2
- absfuyu/extra/da/__init__.py +36 -0
- absfuyu/extra/da/dadf.py +1177 -0
- absfuyu/extra/da/dadf_base.py +186 -0
- absfuyu/extra/da/df_func.py +97 -0
- absfuyu/extra/da/mplt.py +219 -0
- absfuyu/extra/data_analysis.py +10 -1067
- absfuyu/fun/__init__.py +2 -2
- absfuyu/fun/tarot.py +2 -2
- absfuyu/game/__init__.py +2 -2
- absfuyu/game/game_stat.py +2 -2
- absfuyu/game/sudoku.py +2 -2
- absfuyu/game/tictactoe.py +2 -3
- absfuyu/game/wordle.py +2 -2
- absfuyu/general/__init__.py +2 -2
- absfuyu/general/content.py +2 -2
- absfuyu/general/human.py +2 -2
- absfuyu/general/shape.py +2 -2
- absfuyu/logger.py +2 -2
- absfuyu/pkg_data/__init__.py +2 -2
- absfuyu/pkg_data/deprecated.py +2 -2
- absfuyu/sort.py +2 -2
- absfuyu/tools/__init__.py +28 -2
- absfuyu/tools/checksum.py +27 -7
- absfuyu/tools/converter.py +120 -34
- absfuyu/tools/generator.py +251 -110
- absfuyu/tools/inspector.py +463 -0
- absfuyu/tools/keygen.py +2 -2
- absfuyu/tools/obfuscator.py +45 -7
- absfuyu/tools/passwordlib.py +88 -24
- absfuyu/tools/shutdownizer.py +2 -2
- absfuyu/tools/web.py +2 -2
- absfuyu/typings.py +136 -0
- absfuyu/util/__init__.py +18 -4
- absfuyu/util/api.py +36 -16
- absfuyu/util/json_method.py +43 -14
- absfuyu/util/lunar.py +2 -2
- absfuyu/util/path.py +190 -82
- absfuyu/util/performance.py +122 -7
- absfuyu/util/shorten_number.py +40 -10
- absfuyu/util/text_table.py +306 -0
- absfuyu/util/zipped.py +8 -7
- absfuyu/version.py +2 -2
- {absfuyu-5.0.1.dist-info → absfuyu-5.2.0.dist-info}/METADATA +9 -2
- absfuyu-5.2.0.dist-info/RECORD +76 -0
- absfuyu-5.0.1.dist-info/RECORD +0 -68
- {absfuyu-5.0.1.dist-info → absfuyu-5.2.0.dist-info}/WHEEL +0 -0
- {absfuyu-5.0.1.dist-info → absfuyu-5.2.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-5.0.1.dist-info → absfuyu-5.2.0.dist-info}/licenses/LICENSE +0 -0
absfuyu/dxt/listext.py
CHANGED
|
@@ -3,8 +3,8 @@ Absfuyu: Data Extension
|
|
|
3
3
|
-----------------------
|
|
4
4
|
list extension
|
|
5
5
|
|
|
6
|
-
Version: 5.
|
|
7
|
-
Date updated:
|
|
6
|
+
Version: 5.2.0
|
|
7
|
+
Date updated: 15/03/2025 (dd/mm/yyyy)
|
|
8
8
|
"""
|
|
9
9
|
|
|
10
10
|
# Module Package
|
|
@@ -17,12 +17,13 @@ __all__ = ["ListExt"]
|
|
|
17
17
|
import operator
|
|
18
18
|
import random
|
|
19
19
|
from collections import Counter
|
|
20
|
-
from collections.abc import Callable
|
|
20
|
+
from collections.abc import Callable, Iterable
|
|
21
21
|
from itertools import accumulate, chain, groupby
|
|
22
|
-
from typing import Any, Self
|
|
22
|
+
from typing import Any, Literal, Self, cast, overload
|
|
23
23
|
|
|
24
|
-
from absfuyu.core import ShowAllMethodsMixin
|
|
25
|
-
from absfuyu.
|
|
24
|
+
from absfuyu.core.baseclass import ShowAllMethodsMixin
|
|
25
|
+
from absfuyu.core.docstring import deprecated, versionadded, versionchanged
|
|
26
|
+
from absfuyu.util import set_min_max
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
# Class
|
|
@@ -30,15 +31,20 @@ from absfuyu.util import set_min, set_min_max
|
|
|
30
31
|
class ListExt(ShowAllMethodsMixin, list):
|
|
31
32
|
"""
|
|
32
33
|
``list`` extension
|
|
34
|
+
|
|
35
|
+
>>> # For a list of new methods
|
|
36
|
+
>>> ListExt.show_all_methods()
|
|
33
37
|
"""
|
|
34
38
|
|
|
39
|
+
# Deprecated
|
|
40
|
+
@deprecated("5.2.0", reason="Use ListExt.apply(str) instead")
|
|
35
41
|
def stringify(self) -> Self:
|
|
36
42
|
"""
|
|
37
43
|
Convert all item in ``list`` into string
|
|
38
44
|
|
|
39
45
|
Returns
|
|
40
46
|
-------
|
|
41
|
-
|
|
47
|
+
Self
|
|
42
48
|
A list with all items with type <str`>
|
|
43
49
|
|
|
44
50
|
|
|
@@ -50,6 +56,7 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
50
56
|
"""
|
|
51
57
|
return self.__class__(map(str, self))
|
|
52
58
|
|
|
59
|
+
# Info
|
|
53
60
|
def head(self, number_of_items: int = 5) -> list:
|
|
54
61
|
"""
|
|
55
62
|
Show first ``number_of_items`` items in ``ListExt``
|
|
@@ -90,6 +97,31 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
90
97
|
)
|
|
91
98
|
return self[::-1][:number_of_items][::-1]
|
|
92
99
|
|
|
100
|
+
# Misc
|
|
101
|
+
def apply(self, func: Callable[[Any], Any]) -> Self:
|
|
102
|
+
"""
|
|
103
|
+
Apply function to each entry
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
func : Callable
|
|
108
|
+
Callable function
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
Self
|
|
113
|
+
ListExt
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
Example:
|
|
117
|
+
--------
|
|
118
|
+
>>> test = ListExt([1, 2, 3])
|
|
119
|
+
>>> test.apply(str)
|
|
120
|
+
['1', '2', '3']
|
|
121
|
+
"""
|
|
122
|
+
# return self.__class__(map(func, self))
|
|
123
|
+
return self.__class__(func(x) for x in self)
|
|
124
|
+
|
|
93
125
|
def sorts(self, reverse: bool = False) -> Self:
|
|
94
126
|
"""
|
|
95
127
|
Sort all items (with different type) in ``list``
|
|
@@ -97,13 +129,12 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
97
129
|
Parameters
|
|
98
130
|
----------
|
|
99
131
|
reverse : bool
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
| (Default: ``False``)
|
|
132
|
+
- ``True`` then sort in descending order
|
|
133
|
+
- ``False`` then sort in ascending order (default value)
|
|
103
134
|
|
|
104
135
|
Returns
|
|
105
136
|
-------
|
|
106
|
-
|
|
137
|
+
Self
|
|
107
138
|
A sorted list
|
|
108
139
|
|
|
109
140
|
|
|
@@ -127,6 +158,25 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
127
158
|
# logger.debug(output)
|
|
128
159
|
return self.__class__(output)
|
|
129
160
|
|
|
161
|
+
@overload
|
|
162
|
+
def freq(self) -> dict: ...
|
|
163
|
+
|
|
164
|
+
@overload
|
|
165
|
+
def freq(
|
|
166
|
+
self,
|
|
167
|
+
sort: bool = False,
|
|
168
|
+
num_of_first_char: int | None = None,
|
|
169
|
+
appear_increment: Literal[False] = ...,
|
|
170
|
+
) -> dict: ...
|
|
171
|
+
|
|
172
|
+
@overload
|
|
173
|
+
def freq(
|
|
174
|
+
self,
|
|
175
|
+
sort: bool = False,
|
|
176
|
+
num_of_first_char: int | None = None,
|
|
177
|
+
appear_increment: Literal[True] = ...,
|
|
178
|
+
) -> list[int]: ...
|
|
179
|
+
|
|
130
180
|
def freq(
|
|
131
181
|
self,
|
|
132
182
|
sort: bool = False,
|
|
@@ -138,18 +188,17 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
138
188
|
|
|
139
189
|
Parameters
|
|
140
190
|
----------
|
|
141
|
-
sort : bool
|
|
142
|
-
|
|
143
|
-
|
|
191
|
+
sort : bool, optional
|
|
192
|
+
- ``True``: Sorts the output in ascending order
|
|
193
|
+
- ``False``: No sort (default value)
|
|
144
194
|
|
|
145
|
-
num_of_first_char : int | None
|
|
146
|
-
| Number of first character taken into account to sort
|
|
147
|
-
|
|
|
148
|
-
| (num_of_first_char = ``1``: first character in each item)
|
|
195
|
+
num_of_first_char : int | None, optional
|
|
196
|
+
| Number of first character taken into account to sort, by default ``None``
|
|
197
|
+
| Eg: ``num_of_first_char = 1``: first character of each item
|
|
149
198
|
|
|
150
|
-
appear_increment : bool
|
|
151
|
-
|
|
152
|
-
|
|
199
|
+
appear_increment : bool, optional
|
|
200
|
+
Returns incremental index list of each item when sort,
|
|
201
|
+
by default ``False``
|
|
153
202
|
|
|
154
203
|
Returns
|
|
155
204
|
-------
|
|
@@ -170,7 +219,6 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
170
219
|
>>> test.freq(appear_increment=True)
|
|
171
220
|
[2, 3, 5, 6, 7, 8]
|
|
172
221
|
"""
|
|
173
|
-
|
|
174
222
|
if sort:
|
|
175
223
|
data = self.sorts().copy()
|
|
176
224
|
else:
|
|
@@ -190,7 +238,7 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
190
238
|
|
|
191
239
|
try:
|
|
192
240
|
times_appear = dict(sorted(temp.items()))
|
|
193
|
-
except
|
|
241
|
+
except TypeError:
|
|
194
242
|
times_appear = dict(self.__class__(temp.items()).sorts())
|
|
195
243
|
# logger.debug(times_appear)
|
|
196
244
|
|
|
@@ -203,44 +251,110 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
203
251
|
else:
|
|
204
252
|
return times_appear # character frequency
|
|
205
253
|
|
|
206
|
-
|
|
254
|
+
@versionchanged("5.2.0", reason="New ``recursive`` parameter")
|
|
255
|
+
def flatten(self, recursive: bool = False) -> Self:
|
|
207
256
|
"""
|
|
208
|
-
|
|
257
|
+
Flatten the list
|
|
209
258
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
recursive : bool
|
|
262
|
+
Recursively flatten the list, by default ``False``
|
|
263
|
+
|
|
264
|
+
Returns
|
|
265
|
+
-------
|
|
266
|
+
Self
|
|
267
|
+
Flattened list
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
Example:
|
|
271
|
+
--------
|
|
272
|
+
>>> test = ListExt([["test"], ["test", "test"], ["test"]])
|
|
273
|
+
>>> test.flatten()
|
|
274
|
+
['test', 'test', 'test', 'test']
|
|
275
|
+
"""
|
|
276
|
+
|
|
277
|
+
def instance_checking(item):
|
|
278
|
+
if isinstance(item, str):
|
|
279
|
+
return [item]
|
|
280
|
+
if isinstance(item, Iterable):
|
|
281
|
+
return item
|
|
282
|
+
return [item]
|
|
283
|
+
|
|
284
|
+
# Flatten
|
|
285
|
+
list_of_list = (instance_checking(x) for x in self)
|
|
286
|
+
flattened = self.__class__(chain(*list_of_list))
|
|
287
|
+
|
|
288
|
+
# Recursive
|
|
289
|
+
if recursive:
|
|
290
|
+
|
|
291
|
+
def _condition(item) -> bool:
|
|
292
|
+
if isinstance(item, str):
|
|
293
|
+
return False
|
|
294
|
+
return isinstance(item, Iterable)
|
|
295
|
+
|
|
296
|
+
while any(flattened.apply(_condition)):
|
|
297
|
+
flattened = flattened.flatten()
|
|
298
|
+
|
|
299
|
+
# Return
|
|
300
|
+
return flattened
|
|
301
|
+
|
|
302
|
+
@versionadded("5.2.0")
|
|
303
|
+
def join(self, sep: str = " ", /) -> str:
|
|
304
|
+
"""
|
|
305
|
+
Join every element in list to str (``str.join()`` wrapper).
|
|
214
306
|
|
|
215
307
|
Parameters
|
|
216
308
|
----------
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
the list. These indices are *exclusive* of the starting sublist
|
|
220
|
-
but *inclusive* of the ending sublist.
|
|
309
|
+
sep : str, optional
|
|
310
|
+
Separator between each element, by default ``" "``
|
|
221
311
|
|
|
222
312
|
Returns
|
|
223
313
|
-------
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
defined by the provided split points.
|
|
314
|
+
str
|
|
315
|
+
Joined list
|
|
227
316
|
|
|
228
317
|
|
|
229
318
|
Example:
|
|
230
319
|
--------
|
|
231
|
-
>>>
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
>>>
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
[[1, 1, 2, 3, 3, 4, 5, 6]]
|
|
320
|
+
>>> ListExt(["a", "b", "c"]).join()
|
|
321
|
+
a b c
|
|
322
|
+
|
|
323
|
+
>>> # Also work with non-str type
|
|
324
|
+
>>> ListExt([1, 2, 3]).join()
|
|
325
|
+
1 2 3
|
|
238
326
|
"""
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
327
|
+
try:
|
|
328
|
+
return sep.join(self)
|
|
329
|
+
except TypeError:
|
|
330
|
+
return sep.join(self.apply(str))
|
|
331
|
+
|
|
332
|
+
def numbering(self, start: int = 0) -> Self:
|
|
333
|
+
"""
|
|
334
|
+
Number the item in list
|
|
335
|
+
(``enumerate`` wrapper)
|
|
336
|
+
|
|
337
|
+
Parameters
|
|
338
|
+
----------
|
|
339
|
+
start : int
|
|
340
|
+
Start from which number, by default ``0``
|
|
341
|
+
|
|
342
|
+
Returns
|
|
343
|
+
-------
|
|
344
|
+
Self
|
|
345
|
+
Counted list
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
Example:
|
|
349
|
+
--------
|
|
350
|
+
>>> test = ListExt([9, 9, 9])
|
|
351
|
+
>>> test.numbering()
|
|
352
|
+
[(0, 9), (1, 9), (2, 9)]
|
|
353
|
+
"""
|
|
354
|
+
start = max(start, 0)
|
|
355
|
+
return self.__class__(enumerate(self, start=start))
|
|
243
356
|
|
|
357
|
+
# Random
|
|
244
358
|
def pick_one(self) -> Any:
|
|
245
359
|
"""
|
|
246
360
|
Pick one random items from ``list``
|
|
@@ -272,8 +386,7 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
272
386
|
Parameters
|
|
273
387
|
----------
|
|
274
388
|
number_of_items : int
|
|
275
|
-
|
|
276
|
-
| (Default: ``5``)
|
|
389
|
+
Number random of items, by default ``5``
|
|
277
390
|
|
|
278
391
|
Returns
|
|
279
392
|
-------
|
|
@@ -282,13 +395,15 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
282
395
|
"""
|
|
283
396
|
return [self.pick_one() for _ in range(number_of_items)]
|
|
284
397
|
|
|
398
|
+
# Len
|
|
399
|
+
@versionchanged("5.2.0", reason="Handle more type")
|
|
285
400
|
def len_items(self) -> Self:
|
|
286
401
|
"""
|
|
287
|
-
``len()`` for every item in ``
|
|
402
|
+
``len()`` for every item in ``self``
|
|
288
403
|
|
|
289
404
|
Returns
|
|
290
405
|
-------
|
|
291
|
-
|
|
406
|
+
Self
|
|
292
407
|
List of ``len()``'ed value
|
|
293
408
|
|
|
294
409
|
|
|
@@ -298,14 +413,24 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
298
413
|
>>> test.len_items()
|
|
299
414
|
[3, 3, 5]
|
|
300
415
|
"""
|
|
301
|
-
out = self.__class__([len(str(x)) for x in self])
|
|
302
|
-
# out = ListExt(map(lambda x: len(str(x)), self))
|
|
303
|
-
# logger.debug(out)
|
|
304
|
-
return out
|
|
305
416
|
|
|
306
|
-
|
|
417
|
+
def _len(item: Any) -> int:
|
|
418
|
+
try:
|
|
419
|
+
return len(item)
|
|
420
|
+
except TypeError:
|
|
421
|
+
return len(str(item))
|
|
422
|
+
|
|
423
|
+
return self.__class__([_len(x) for x in self])
|
|
424
|
+
|
|
425
|
+
@versionchanged("5.2.0", reason="New ``recursive`` parameter")
|
|
426
|
+
def mean_len(self, recursive: bool = False) -> float:
|
|
307
427
|
"""
|
|
308
|
-
Average length of every item
|
|
428
|
+
Average length of every item. Returns zero if failed (empty list, ZeroDivisionError).
|
|
429
|
+
|
|
430
|
+
Parameters
|
|
431
|
+
----------
|
|
432
|
+
recursive : bool
|
|
433
|
+
Recursively find the average length of items in nested lists, by default ``False``
|
|
309
434
|
|
|
310
435
|
Returns
|
|
311
436
|
-------
|
|
@@ -319,41 +444,55 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
319
444
|
>>> test.mean_len()
|
|
320
445
|
3.6666666666666665
|
|
321
446
|
"""
|
|
322
|
-
out = sum(self.len_items()) / len(self)
|
|
323
|
-
# logger.debug(out)
|
|
324
|
-
return out
|
|
325
447
|
|
|
326
|
-
|
|
448
|
+
if recursive:
|
|
449
|
+
dat = self.flatten(recursive=recursive)
|
|
450
|
+
else:
|
|
451
|
+
dat = self
|
|
452
|
+
|
|
453
|
+
try:
|
|
454
|
+
return sum(dat.len_items()) / len(dat)
|
|
455
|
+
except ZeroDivisionError:
|
|
456
|
+
return 0.0
|
|
457
|
+
|
|
458
|
+
@versionadded("5.2.0")
|
|
459
|
+
def max_item_len(self, recursive: bool = False) -> int:
|
|
327
460
|
"""
|
|
328
|
-
|
|
461
|
+
Find the maximum length of items in the list.
|
|
329
462
|
|
|
330
463
|
Parameters
|
|
331
464
|
----------
|
|
332
|
-
|
|
333
|
-
|
|
465
|
+
recursive : bool
|
|
466
|
+
Recursively find the maximum length of items in nested lists, by default ``False``
|
|
334
467
|
|
|
335
468
|
Returns
|
|
336
469
|
-------
|
|
337
|
-
|
|
338
|
-
|
|
470
|
+
int
|
|
471
|
+
Maximum length of items
|
|
339
472
|
|
|
340
473
|
|
|
341
474
|
Example:
|
|
342
475
|
--------
|
|
343
|
-
>>> test = ListExt([
|
|
344
|
-
>>> test.
|
|
345
|
-
|
|
476
|
+
>>> test = ListExt(["test", "longer_test"])
|
|
477
|
+
>>> test.max_item_len()
|
|
478
|
+
11
|
|
479
|
+
|
|
480
|
+
>>> test = ListExt([["short"], ["longer_test"]])
|
|
481
|
+
>>> test.max_item_len(recursive=True)
|
|
482
|
+
11
|
|
346
483
|
"""
|
|
347
|
-
|
|
348
|
-
|
|
484
|
+
if recursive:
|
|
485
|
+
return cast(int, max(self.flatten(recursive=True).len_items()))
|
|
486
|
+
return cast(int, max(self.len_items()))
|
|
349
487
|
|
|
488
|
+
# Group/Unique
|
|
350
489
|
def unique(self) -> Self:
|
|
351
490
|
"""
|
|
352
491
|
Remove duplicates
|
|
353
492
|
|
|
354
493
|
Returns
|
|
355
494
|
-------
|
|
356
|
-
|
|
495
|
+
Self
|
|
357
496
|
Duplicates removed list
|
|
358
497
|
|
|
359
498
|
|
|
@@ -371,7 +510,7 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
371
510
|
|
|
372
511
|
Returns
|
|
373
512
|
-------
|
|
374
|
-
|
|
513
|
+
Self
|
|
375
514
|
Grouped value
|
|
376
515
|
|
|
377
516
|
|
|
@@ -423,7 +562,7 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
423
562
|
iter = self.copy()
|
|
424
563
|
|
|
425
564
|
# Init loop
|
|
426
|
-
for _ in range(
|
|
565
|
+
for _ in range(max(max_loop, 3)):
|
|
427
566
|
temp: dict[Any, list] = {}
|
|
428
567
|
# Make dict{key: all `item` that contains `key`}
|
|
429
568
|
for item in iter:
|
|
@@ -441,68 +580,116 @@ class ListExt(ShowAllMethodsMixin, list):
|
|
|
441
580
|
|
|
442
581
|
return list(x for x, _ in groupby(iter))
|
|
443
582
|
|
|
444
|
-
|
|
583
|
+
# Slicing
|
|
584
|
+
def slice_points(self, points: list[int]) -> Self:
|
|
445
585
|
"""
|
|
446
|
-
|
|
586
|
+
Splits a list into sublists based on specified split points (indices).
|
|
587
|
+
|
|
588
|
+
This method divides the original list into multiple sublists. The ``points``
|
|
589
|
+
argument provides the indices at which the list should be split. The resulting
|
|
590
|
+
list of lists contains the sublists created by these splits. The original
|
|
591
|
+
list is not modified.
|
|
592
|
+
|
|
593
|
+
Parameters
|
|
594
|
+
----------
|
|
595
|
+
points : list
|
|
596
|
+
A list of integer indices representing the points at which to split
|
|
597
|
+
the list. These indices are *exclusive* of the starting sublist
|
|
598
|
+
but *inclusive* of the ending sublist.
|
|
447
599
|
|
|
448
600
|
Returns
|
|
449
601
|
-------
|
|
450
|
-
|
|
451
|
-
|
|
602
|
+
Self | list[list]
|
|
603
|
+
A list of lists, where each inner list is a slice of the original list
|
|
604
|
+
defined by the provided split points.
|
|
452
605
|
|
|
453
606
|
|
|
454
607
|
Example:
|
|
455
608
|
--------
|
|
456
|
-
>>> test = ListExt([
|
|
457
|
-
>>> test.
|
|
458
|
-
[
|
|
609
|
+
>>> test = ListExt([1, 1, 2, 3, 3, 4, 5, 6])
|
|
610
|
+
>>> test.slice_points([2, 5])
|
|
611
|
+
[[1, 1], [2, 3, 3], [4, 5, 6]]
|
|
612
|
+
>>> test.slice_points([0, 1, 2, 3, 4, 5, 6, 7, 8])
|
|
613
|
+
[[], [1], [1], [2], [3], [3], [4], [5], [6]]
|
|
614
|
+
>>> test.slice_points([])
|
|
615
|
+
[[1, 1, 2, 3, 3, 4, 5, 6]]
|
|
459
616
|
"""
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
temp = list(map(lambda x: x if isinstance(x, list) else [x], self))
|
|
465
|
-
return self.__class__(chain(*temp))
|
|
617
|
+
points.append(len(self))
|
|
618
|
+
data = self.copy()
|
|
619
|
+
# return [data[points[i]:points[i+1]] for i in range(len(points)-1)]
|
|
620
|
+
return self.__class__(data[i1:i2] for i1, i2 in zip([0] + points[:-1], points))
|
|
466
621
|
|
|
467
|
-
|
|
622
|
+
@versionadded("5.1.0")
|
|
623
|
+
def split_chunk(self, chunk_size: int) -> Self:
|
|
468
624
|
"""
|
|
469
|
-
|
|
470
|
-
(``enumerate`` wrapper)
|
|
625
|
+
Split list into smaller chunks
|
|
471
626
|
|
|
472
627
|
Parameters
|
|
473
628
|
----------
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
(Default: ``0``)
|
|
629
|
+
chunk_size : int
|
|
630
|
+
Chunk size, minimum: ``1``
|
|
477
631
|
|
|
478
632
|
Returns
|
|
479
633
|
-------
|
|
480
|
-
|
|
481
|
-
|
|
634
|
+
Self | list[list]
|
|
635
|
+
List of chunk
|
|
482
636
|
|
|
483
637
|
|
|
484
638
|
Example:
|
|
485
639
|
--------
|
|
486
|
-
>>>
|
|
487
|
-
|
|
488
|
-
[(0, 9), (1, 9), (2, 9)]
|
|
640
|
+
>>> ListExt([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]).split_chunk(5)
|
|
641
|
+
[[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1]]
|
|
489
642
|
"""
|
|
490
|
-
|
|
491
|
-
return self.
|
|
643
|
+
slice_points = list(range(0, len(self), max(chunk_size, 1)))[1:]
|
|
644
|
+
return self.slice_points(slice_points)
|
|
492
645
|
|
|
493
|
-
@
|
|
494
|
-
|
|
495
|
-
def _group_by_unique(iterable: list) -> list[list]:
|
|
496
|
-
"""
|
|
497
|
-
Static method for ``group_by_unique``
|
|
646
|
+
@versionadded("5.2.0") # no test case yet
|
|
647
|
+
def wrap_to_column(self, width: int, margin: int = 4) -> Self:
|
|
498
648
|
"""
|
|
499
|
-
|
|
649
|
+
Arrange list[str] items into aligned text columns (for printing)
|
|
650
|
+
with automatic column count calculation.
|
|
500
651
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
652
|
+
Parameters
|
|
653
|
+
----------
|
|
654
|
+
width : int
|
|
655
|
+
Total available display width (must be >= ``margin``)
|
|
656
|
+
|
|
657
|
+
margin : int, optional
|
|
658
|
+
Reserved space for borders/padding, by default ``4``
|
|
659
|
+
|
|
660
|
+
Returns
|
|
661
|
+
-------
|
|
662
|
+
Self
|
|
663
|
+
New instance type[list[str]] with formatted column strings.
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
Example:
|
|
667
|
+
--------
|
|
668
|
+
>>> items = ListExt(["apple", "banana", "cherry", "date"])
|
|
669
|
+
>>> print(items.wrap_to_column(30))
|
|
670
|
+
['apple banana cherry ', 'date ']
|
|
671
|
+
|
|
672
|
+
>>> items.wrap_to_column(15)
|
|
673
|
+
['apple ', 'banana ', 'cherry ', 'date ']
|
|
506
674
|
"""
|
|
507
|
-
|
|
508
|
-
|
|
675
|
+
|
|
676
|
+
max_item_length = self.max_item_len() + 1 # +1 for spacing
|
|
677
|
+
available_width = max(width, 4) - max(margin, 2) # Set boundary
|
|
678
|
+
|
|
679
|
+
# Calculate how many columns of text
|
|
680
|
+
column_count = (
|
|
681
|
+
max(1, available_width // max_item_length) if max_item_length > 0 else 1
|
|
682
|
+
)
|
|
683
|
+
|
|
684
|
+
# splitted_chunk: list[list[str]] = self.split_chunk(cols)
|
|
685
|
+
# mod_chunk = self.__class__(
|
|
686
|
+
# [[x.ljust(max_name_len, " ") for x in chunk] for chunk in splitted_chunk]
|
|
687
|
+
# ).apply(lambda x: "".join(x))
|
|
688
|
+
|
|
689
|
+
def mod_item(item: list[str]) -> str:
|
|
690
|
+
# Set width for str item and join them together
|
|
691
|
+
return "".join(x.ljust(max_item_length, " ") for x in item)
|
|
692
|
+
|
|
693
|
+
mod_chunk = self.split_chunk(column_count).apply(mod_item)
|
|
694
|
+
|
|
695
|
+
return mod_chunk
|