pyochain 0.5.3__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.
- pyochain/__init__.py +5 -0
- pyochain/_core/__init__.py +23 -0
- pyochain/_core/_format.py +34 -0
- pyochain/_core/_main.py +205 -0
- pyochain/_core/_protocols.py +38 -0
- pyochain/_dict/__init__.py +3 -0
- pyochain/_dict/_filters.py +268 -0
- pyochain/_dict/_groups.py +175 -0
- pyochain/_dict/_iter.py +135 -0
- pyochain/_dict/_joins.py +139 -0
- pyochain/_dict/_main.py +113 -0
- pyochain/_dict/_maps.py +142 -0
- pyochain/_dict/_nested.py +272 -0
- pyochain/_dict/_process.py +204 -0
- pyochain/_iter/__init__.py +3 -0
- pyochain/_iter/_aggregations.py +324 -0
- pyochain/_iter/_booleans.py +227 -0
- pyochain/_iter/_dicts.py +243 -0
- pyochain/_iter/_eager.py +233 -0
- pyochain/_iter/_filters.py +510 -0
- pyochain/_iter/_joins.py +404 -0
- pyochain/_iter/_lists.py +308 -0
- pyochain/_iter/_main.py +466 -0
- pyochain/_iter/_maps.py +360 -0
- pyochain/_iter/_partitions.py +145 -0
- pyochain/_iter/_process.py +366 -0
- pyochain/_iter/_rolling.py +241 -0
- pyochain/_iter/_tuples.py +326 -0
- pyochain/py.typed +0 -0
- pyochain-0.5.3.dist-info/METADATA +261 -0
- pyochain-0.5.3.dist-info/RECORD +32 -0
- pyochain-0.5.3.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import functools
|
|
4
|
+
import statistics
|
|
5
|
+
from collections.abc import Callable, Iterable
|
|
6
|
+
from typing import TYPE_CHECKING, Literal, NamedTuple
|
|
7
|
+
|
|
8
|
+
import cytoolz as cz
|
|
9
|
+
import more_itertools as mit
|
|
10
|
+
|
|
11
|
+
from .._core import IterWrapper
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from ._main import Iter
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Unzipped[T, V](NamedTuple):
|
|
18
|
+
first: Iter[T]
|
|
19
|
+
second: Iter[V]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class BaseAgg[T](IterWrapper[T]):
|
|
23
|
+
def unzip[U, V](self: IterWrapper[tuple[U, V]]) -> Unzipped[U, V]:
|
|
24
|
+
"""
|
|
25
|
+
Converts an iterator of pairs into a pair of iterators.
|
|
26
|
+
|
|
27
|
+
`Iter.unzip()` consumes the iterator of pairs.
|
|
28
|
+
|
|
29
|
+
Returns an Unzipped NamedTuple, containing two iterators:
|
|
30
|
+
|
|
31
|
+
- one from the left elements of the pairs
|
|
32
|
+
- one from the right elements.
|
|
33
|
+
|
|
34
|
+
This function is, in some sense, the opposite of zip.
|
|
35
|
+
```python
|
|
36
|
+
>>> import pyochain as pc
|
|
37
|
+
>>> data = [(1, "a"), (2, "b"), (3, "c")]
|
|
38
|
+
>>> unzipped = pc.Iter.from_(data).unzip()
|
|
39
|
+
>>> unzipped.first.into(list)
|
|
40
|
+
[1, 2, 3]
|
|
41
|
+
>>> unzipped.second.into(list)
|
|
42
|
+
['a', 'b', 'c']
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
"""
|
|
46
|
+
from ._main import Iter
|
|
47
|
+
|
|
48
|
+
def _unzip(data: Iterable[tuple[U, V]]) -> Unzipped[U, V]:
|
|
49
|
+
d: list[tuple[U, V]] = list(data)
|
|
50
|
+
return Unzipped(Iter(x[0] for x in d), Iter(x[1] for x in d))
|
|
51
|
+
|
|
52
|
+
return self.into(_unzip)
|
|
53
|
+
|
|
54
|
+
def reduce(self, func: Callable[[T, T], T]) -> T:
|
|
55
|
+
"""
|
|
56
|
+
Apply a function of two arguments cumulatively to the items of an iterable, from left to right.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
func: Function to apply cumulatively to the items of the iterable.
|
|
60
|
+
|
|
61
|
+
This effectively reduces the iterable to a single value.
|
|
62
|
+
|
|
63
|
+
If initial is present, it is placed before the items of the iterable in the calculation.
|
|
64
|
+
|
|
65
|
+
It then serves as a default when the iterable is empty.
|
|
66
|
+
```python
|
|
67
|
+
>>> import pyochain as pc
|
|
68
|
+
>>> pc.Iter.from_([1, 2, 3]).reduce(lambda a, b: a + b)
|
|
69
|
+
6
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
"""
|
|
73
|
+
return self.into(functools.partial(functools.reduce, func))
|
|
74
|
+
|
|
75
|
+
def combination_index(self, r: Iterable[T]) -> int:
|
|
76
|
+
"""
|
|
77
|
+
Equivalent to list(combinations(iterable, r)).index(element).
|
|
78
|
+
|
|
79
|
+
Args:
|
|
80
|
+
r: The combination to find the index of.
|
|
81
|
+
|
|
82
|
+
The subsequences of iterable that are of length r can be ordered lexicographically.
|
|
83
|
+
|
|
84
|
+
combination_index computes the index of the first element, without computing the previous combinations.
|
|
85
|
+
|
|
86
|
+
ValueError will be raised if the given element isn't one of the combinations of iterable.
|
|
87
|
+
```python
|
|
88
|
+
>>> import pyochain as pc
|
|
89
|
+
>>> pc.Iter.from_("abcdefg").combination_index("adf")
|
|
90
|
+
10
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
"""
|
|
94
|
+
return self.into(functools.partial(mit.combination_index, r))
|
|
95
|
+
|
|
96
|
+
def first(self) -> T:
|
|
97
|
+
"""
|
|
98
|
+
Return the first element.
|
|
99
|
+
```python
|
|
100
|
+
>>> import pyochain as pc
|
|
101
|
+
>>> pc.Iter.from_([9]).first()
|
|
102
|
+
9
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
"""
|
|
106
|
+
return self.into(cz.itertoolz.first)
|
|
107
|
+
|
|
108
|
+
def second(self) -> T:
|
|
109
|
+
"""
|
|
110
|
+
Return the second element.
|
|
111
|
+
```python
|
|
112
|
+
>>> import pyochain as pc
|
|
113
|
+
>>> pc.Iter.from_([9, 8]).second()
|
|
114
|
+
8
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
"""
|
|
118
|
+
return self.into(cz.itertoolz.second)
|
|
119
|
+
|
|
120
|
+
def last(self) -> T:
|
|
121
|
+
"""
|
|
122
|
+
Return the last element.
|
|
123
|
+
```python
|
|
124
|
+
>>> import pyochain as pc
|
|
125
|
+
>>> pc.Iter.from_([7, 8, 9]).last()
|
|
126
|
+
9
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
"""
|
|
130
|
+
return self.into(cz.itertoolz.last)
|
|
131
|
+
|
|
132
|
+
def count(self) -> int:
|
|
133
|
+
"""
|
|
134
|
+
Return the length of the sequence.
|
|
135
|
+
Like the builtin len but works on lazy sequences.
|
|
136
|
+
```python
|
|
137
|
+
>>> import pyochain as pc
|
|
138
|
+
>>> pc.Iter.from_([1, 2]).count()
|
|
139
|
+
2
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
"""
|
|
143
|
+
return self.into(cz.itertoolz.count)
|
|
144
|
+
|
|
145
|
+
def item(self, index: int) -> T:
|
|
146
|
+
"""
|
|
147
|
+
Return item at index.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
index: The index of the item to retrieve.
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
>>> import pyochain as pc
|
|
154
|
+
>>> pc.Iter.from_([10, 20]).item(1)
|
|
155
|
+
20
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
"""
|
|
159
|
+
return self.into(functools.partial(cz.itertoolz.nth, index))
|
|
160
|
+
|
|
161
|
+
def argmax[U](self, key: Callable[[T], U] | None = None) -> int:
|
|
162
|
+
"""
|
|
163
|
+
Index of the first occurrence of a maximum value in an iterable.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
key: Optional function to determine the value for comparison.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
>>> import pyochain as pc
|
|
170
|
+
>>> pc.Iter.from_("abcdefghabcd").argmax()
|
|
171
|
+
7
|
|
172
|
+
>>> pc.Iter.from_([0, 1, 2, 3, 3, 2, 1, 0]).argmax()
|
|
173
|
+
3
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
For example, identify the best machine learning model:
|
|
177
|
+
```python
|
|
178
|
+
>>> models = pc.Iter.from_(["svm", "random forest", "knn", "naïve bayes"])
|
|
179
|
+
>>> accuracy = pc.Seq([68, 61, 84, 72])
|
|
180
|
+
>>> # Most accurate model
|
|
181
|
+
>>> models.item(accuracy.argmax())
|
|
182
|
+
'knn'
|
|
183
|
+
>>>
|
|
184
|
+
>>> # Best accuracy
|
|
185
|
+
>>> accuracy.into(max)
|
|
186
|
+
84
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
"""
|
|
190
|
+
return self.into(mit.argmax, key=key)
|
|
191
|
+
|
|
192
|
+
def argmin[U](self, key: Callable[[T], U] | None = None) -> int:
|
|
193
|
+
"""
|
|
194
|
+
Index of the first occurrence of a minimum value in an iterable.
|
|
195
|
+
|
|
196
|
+
Args:
|
|
197
|
+
key: Optional function to determine the value for comparison.
|
|
198
|
+
|
|
199
|
+
```python
|
|
200
|
+
>>> import pyochain as pc
|
|
201
|
+
>>> pc.Iter.from_("efghabcdijkl").argmin()
|
|
202
|
+
4
|
|
203
|
+
>>> pc.Iter.from_([3, 2, 1, 0, 4, 2, 1, 0]).argmin()
|
|
204
|
+
3
|
|
205
|
+
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
For example, look up a label corresponding to the position of a value that minimizes a cost function:
|
|
209
|
+
```python
|
|
210
|
+
>>> def cost(x):
|
|
211
|
+
... "Days for a wound to heal given a subject's age."
|
|
212
|
+
... return x**2 - 20 * x + 150
|
|
213
|
+
>>> labels = pc.Iter.from_(["homer", "marge", "bart", "lisa", "maggie"])
|
|
214
|
+
>>> ages = pc.Seq([35, 30, 10, 9, 1])
|
|
215
|
+
>>> # Fastest healing family member
|
|
216
|
+
>>> labels.item(ages.argmin(key=cost))
|
|
217
|
+
'bart'
|
|
218
|
+
>>> # Age with fastest healing
|
|
219
|
+
>>> ages.into(min, key=cost)
|
|
220
|
+
10
|
|
221
|
+
|
|
222
|
+
```
|
|
223
|
+
"""
|
|
224
|
+
return self.into(mit.argmin, key=key)
|
|
225
|
+
|
|
226
|
+
def sum[U: int | float](self: IterWrapper[U]) -> U | Literal[0]:
|
|
227
|
+
"""
|
|
228
|
+
Return the sum of the sequence.
|
|
229
|
+
```python
|
|
230
|
+
>>> import pyochain as pc
|
|
231
|
+
>>> pc.Iter.from_([1, 2, 3]).sum()
|
|
232
|
+
6
|
|
233
|
+
|
|
234
|
+
```
|
|
235
|
+
"""
|
|
236
|
+
return self.into(sum)
|
|
237
|
+
|
|
238
|
+
def min[U: int | float](self: IterWrapper[U]) -> U:
|
|
239
|
+
"""
|
|
240
|
+
Return the minimum of the sequence.
|
|
241
|
+
```python
|
|
242
|
+
>>> import pyochain as pc
|
|
243
|
+
>>> pc.Iter.from_([3, 1, 2]).min()
|
|
244
|
+
1
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
"""
|
|
248
|
+
return self.into(min)
|
|
249
|
+
|
|
250
|
+
def max[U: int | float](self: IterWrapper[U]) -> U:
|
|
251
|
+
"""
|
|
252
|
+
Return the maximum of the sequence.
|
|
253
|
+
```python
|
|
254
|
+
>>> import pyochain as pc
|
|
255
|
+
>>> pc.Iter.from_([3, 1, 2]).max()
|
|
256
|
+
3
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
"""
|
|
260
|
+
return self.into(max)
|
|
261
|
+
|
|
262
|
+
def mean[U: int | float](self: IterWrapper[U]) -> float:
|
|
263
|
+
"""
|
|
264
|
+
Return the mean of the sequence.
|
|
265
|
+
```python
|
|
266
|
+
>>> import pyochain as pc
|
|
267
|
+
>>> pc.Iter.from_([1, 2, 3]).mean()
|
|
268
|
+
2
|
|
269
|
+
|
|
270
|
+
```
|
|
271
|
+
"""
|
|
272
|
+
return self.into(statistics.mean)
|
|
273
|
+
|
|
274
|
+
def median[U: int | float](self: IterWrapper[U]) -> float:
|
|
275
|
+
"""
|
|
276
|
+
Return the median of the sequence.
|
|
277
|
+
```python
|
|
278
|
+
>>> import pyochain as pc
|
|
279
|
+
>>> pc.Iter.from_([1, 3, 2]).median()
|
|
280
|
+
2
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
"""
|
|
284
|
+
return self.into(statistics.median)
|
|
285
|
+
|
|
286
|
+
def mode[U: int | float](self: IterWrapper[U]) -> U:
|
|
287
|
+
"""
|
|
288
|
+
Return the mode of the sequence.
|
|
289
|
+
```python
|
|
290
|
+
>>> import pyochain as pc
|
|
291
|
+
>>> pc.Iter.from_([1, 2, 2, 3]).mode()
|
|
292
|
+
2
|
|
293
|
+
|
|
294
|
+
```
|
|
295
|
+
"""
|
|
296
|
+
return self.into(statistics.mode)
|
|
297
|
+
|
|
298
|
+
def stdev[U: int | float](
|
|
299
|
+
self: IterWrapper[U],
|
|
300
|
+
) -> float:
|
|
301
|
+
"""
|
|
302
|
+
Return the standard deviation of the sequence.
|
|
303
|
+
```python
|
|
304
|
+
>>> import pyochain as pc
|
|
305
|
+
>>> pc.Iter.from_([1, 2, 3]).stdev()
|
|
306
|
+
1.0
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
"""
|
|
310
|
+
return self.into(statistics.stdev)
|
|
311
|
+
|
|
312
|
+
def variance[U: int | float](
|
|
313
|
+
self: IterWrapper[U],
|
|
314
|
+
) -> float:
|
|
315
|
+
"""
|
|
316
|
+
Return the variance of the sequence.
|
|
317
|
+
```python
|
|
318
|
+
>>> import pyochain as pc
|
|
319
|
+
>>> pc.Iter.from_([1, 2, 3, 7, 8]).variance()
|
|
320
|
+
9.7
|
|
321
|
+
|
|
322
|
+
```
|
|
323
|
+
"""
|
|
324
|
+
return self.into(statistics.variance)
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Callable, Iterable
|
|
4
|
+
from typing import overload
|
|
5
|
+
|
|
6
|
+
import cytoolz as cz
|
|
7
|
+
import more_itertools as mit
|
|
8
|
+
|
|
9
|
+
from .._core import IterWrapper
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BaseBool[T](IterWrapper[T]):
|
|
13
|
+
def all(self, predicate: Callable[[T], bool] = lambda x: bool(x)) -> bool:
|
|
14
|
+
"""
|
|
15
|
+
Tests if every element of the iterator matches a predicate.
|
|
16
|
+
|
|
17
|
+
`Iter.all()` takes a closure that returns true or false.
|
|
18
|
+
|
|
19
|
+
It applies this closure to each element of the iterator, and if they all return true, then so does `Iter.all()`.
|
|
20
|
+
|
|
21
|
+
If any of them return false, it returns false.
|
|
22
|
+
|
|
23
|
+
An empty iterator returns true.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
predicate: Function to evaluate each item. Defaults to checking truthiness.
|
|
27
|
+
Example:
|
|
28
|
+
```python
|
|
29
|
+
>>> import pyochain as pc
|
|
30
|
+
>>> pc.Iter.from_([1, True]).all()
|
|
31
|
+
True
|
|
32
|
+
>>> pc.Iter.from_([]).all()
|
|
33
|
+
True
|
|
34
|
+
>>> pc.Iter.from_([1, 0]).all()
|
|
35
|
+
False
|
|
36
|
+
>>> def is_even(x: int) -> bool:
|
|
37
|
+
... return x % 2 == 0
|
|
38
|
+
>>> pc.Iter.from_([2, 4, 6]).all(is_even)
|
|
39
|
+
True
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def _all(data: Iterable[T]) -> bool:
|
|
45
|
+
return all(predicate(x) for x in data)
|
|
46
|
+
|
|
47
|
+
return self.into(_all)
|
|
48
|
+
|
|
49
|
+
def any(self, predicate: Callable[[T], bool] = lambda x: bool(x)) -> bool:
|
|
50
|
+
"""
|
|
51
|
+
Tests if any element of the iterator matches a predicate.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
`Iter.any()` takes a closure that returns true or false.
|
|
55
|
+
|
|
56
|
+
It applies this closure to each element of the iterator, and if any of them return true, then so does `Iter.any()`.
|
|
57
|
+
|
|
58
|
+
If they all return false, it returns false.
|
|
59
|
+
|
|
60
|
+
An empty iterator returns false.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
predicate: Function to evaluate each item. Defaults to checking truthiness.
|
|
64
|
+
Example:
|
|
65
|
+
```python
|
|
66
|
+
>>> import pyochain as pc
|
|
67
|
+
>>> pc.Iter.from_([0, 1]).any()
|
|
68
|
+
True
|
|
69
|
+
>>> pc.Iter.from_(range(0)).any()
|
|
70
|
+
False
|
|
71
|
+
>>> def is_even(x: int) -> bool:
|
|
72
|
+
... return x % 2 == 0
|
|
73
|
+
>>> pc.Iter.from_([1, 3, 4]).any(is_even)
|
|
74
|
+
True
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
def _any(data: Iterable[T]) -> bool:
|
|
80
|
+
return any(predicate(x) for x in data)
|
|
81
|
+
|
|
82
|
+
return self.into(_any)
|
|
83
|
+
|
|
84
|
+
def is_distinct(self) -> bool:
|
|
85
|
+
"""
|
|
86
|
+
Return True if all items are distinct.
|
|
87
|
+
```python
|
|
88
|
+
>>> import pyochain as pc
|
|
89
|
+
>>> pc.Iter.from_([1, 2]).is_distinct()
|
|
90
|
+
True
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
"""
|
|
94
|
+
return self.into(cz.itertoolz.isdistinct)
|
|
95
|
+
|
|
96
|
+
def all_equal[U](self, key: Callable[[T], U] | None = None) -> bool:
|
|
97
|
+
"""
|
|
98
|
+
Return True if all items are equal.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
key: Function to transform items before comparison. Defaults to None.
|
|
102
|
+
Example:
|
|
103
|
+
```python
|
|
104
|
+
>>> import pyochain as pc
|
|
105
|
+
>>> pc.Iter.from_([1, 1, 1]).all_equal()
|
|
106
|
+
True
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
A function that accepts a single argument and returns a transformed version of each input item can be specified with key:
|
|
110
|
+
```python
|
|
111
|
+
>>> pc.Iter.from_("AaaA").all_equal(key=str.casefold)
|
|
112
|
+
True
|
|
113
|
+
>>> pc.Iter.from_([1, 2, 3]).all_equal(key=lambda x: x < 10)
|
|
114
|
+
True
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
"""
|
|
118
|
+
return self.into(mit.all_equal, key=key)
|
|
119
|
+
|
|
120
|
+
def all_unique[U](self, key: Callable[[T], U] | None = None) -> bool:
|
|
121
|
+
"""
|
|
122
|
+
Returns True if all the elements of iterable are unique.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
key: Function to transform items before comparison. Defaults to None.
|
|
126
|
+
Example:
|
|
127
|
+
```python
|
|
128
|
+
>>> import pyochain as pc
|
|
129
|
+
>>> pc.Iter.from_("ABCB").all_unique()
|
|
130
|
+
False
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
If a key function is specified, it will be used to make comparisons.
|
|
134
|
+
```python
|
|
135
|
+
>>> pc.Iter.from_("ABCb").all_unique()
|
|
136
|
+
True
|
|
137
|
+
>>> pc.Iter.from_("ABCb").all_unique(str.lower)
|
|
138
|
+
False
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
The function returns as soon as the first non-unique element is encountered.
|
|
142
|
+
|
|
143
|
+
Iterables with a mix of hashable and unhashable items can be used, but the function will be slower for unhashable items
|
|
144
|
+
|
|
145
|
+
"""
|
|
146
|
+
return self.into(mit.all_unique, key=key)
|
|
147
|
+
|
|
148
|
+
def is_sorted[U](
|
|
149
|
+
self,
|
|
150
|
+
key: Callable[[T], U] | None = None,
|
|
151
|
+
reverse: bool = False,
|
|
152
|
+
strict: bool = False,
|
|
153
|
+
) -> bool:
|
|
154
|
+
"""
|
|
155
|
+
Returns True if the items of iterable are in sorted order.
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
key: Function to transform items before comparison. Defaults to None.
|
|
159
|
+
reverse: Whether to check for descending order. Defaults to False.
|
|
160
|
+
strict: Whether to enforce strict sorting (no equal elements). Defaults to False.
|
|
161
|
+
Example:
|
|
162
|
+
```python
|
|
163
|
+
>>> import pyochain as pc
|
|
164
|
+
>>> pc.Iter.from_(["1", "2", "3", "4", "5"]).is_sorted(key=int)
|
|
165
|
+
True
|
|
166
|
+
>>> pc.Iter.from_([5, 4, 3, 1, 2]).is_sorted(reverse=True)
|
|
167
|
+
False
|
|
168
|
+
|
|
169
|
+
If strict, tests for strict sorting, that is, returns False if equal elements are found:
|
|
170
|
+
```python
|
|
171
|
+
>>> pc.Iter.from_([1, 2, 2]).is_sorted()
|
|
172
|
+
True
|
|
173
|
+
>>> pc.Iter.from_([1, 2, 2]).is_sorted(strict=True)
|
|
174
|
+
False
|
|
175
|
+
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
The function returns False after encountering the first out-of-order item.
|
|
179
|
+
|
|
180
|
+
This means it may produce results that differ from the built-in sorted function for objects with unusual comparison dynamics (like math.nan).
|
|
181
|
+
|
|
182
|
+
If there are no out-of-order items, the iterable is exhausted.
|
|
183
|
+
"""
|
|
184
|
+
return self.into(mit.is_sorted, key=key, reverse=reverse, strict=strict)
|
|
185
|
+
|
|
186
|
+
@overload
|
|
187
|
+
def find(
|
|
188
|
+
self, default: None = None, predicate: Callable[[T], bool] | None = ...
|
|
189
|
+
) -> T | None: ...
|
|
190
|
+
@overload
|
|
191
|
+
def find(self, default: T, predicate: Callable[[T], bool] | None = ...) -> T: ...
|
|
192
|
+
|
|
193
|
+
def find[U](
|
|
194
|
+
self, default: U = None, predicate: Callable[[T], bool] | None = None
|
|
195
|
+
) -> U | T:
|
|
196
|
+
"""
|
|
197
|
+
Searches for an element of an iterator that satisfies a `predicate`, by:
|
|
198
|
+
|
|
199
|
+
- Taking a closure that returns true or false as `predicate` (optional).
|
|
200
|
+
- Using the identity function if no `predicate` is provided.
|
|
201
|
+
- Applying this closure to each element of the iterator.
|
|
202
|
+
- Returning the first element that satisfies the `predicate`.
|
|
203
|
+
|
|
204
|
+
If all the elements return false, `Iter.find()` returns the default value.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
default: Value to return if no element satisfies the predicate. Defaults to None.
|
|
208
|
+
predicate: Function to evaluate each item. Defaults to checking truthiness.
|
|
209
|
+
Example:
|
|
210
|
+
```python
|
|
211
|
+
>>> import pyochain as pc
|
|
212
|
+
>>> def gt_five(x: int) -> bool:
|
|
213
|
+
... return x > 5
|
|
214
|
+
>>>
|
|
215
|
+
>>> def gt_nine(x: int) -> bool:
|
|
216
|
+
... return x > 9
|
|
217
|
+
>>>
|
|
218
|
+
>>> pc.Iter.from_(range(10)).find()
|
|
219
|
+
1
|
|
220
|
+
>>> pc.Iter.from_(range(10)).find(predicate=gt_five)
|
|
221
|
+
6
|
|
222
|
+
>>> pc.Iter.from_(range(10)).find(default="missing", predicate=gt_nine)
|
|
223
|
+
'missing'
|
|
224
|
+
|
|
225
|
+
```
|
|
226
|
+
"""
|
|
227
|
+
return self.into(mit.first_true, default, predicate)
|