Passed
Push — master ( c6ca89...6947de )
by Pol
03:50 queued 01:45
created

Collection::countIn()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 1
dl 0
loc 9
ccs 8
cts 8
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace loophp\collection;
6
7
use Closure;
8
use Countable;
9
use Doctrine\Common\Collections\Criteria;
10
use Generator;
11
use JsonSerializable;
12
use loophp\collection\Contract\Collection as CollectionInterface;
13
use loophp\collection\Contract\Operation as OperationInterface;
14
use loophp\collection\Utils\CallbacksArrayReducer;
15
use loophp\iterators\ClosureIteratorAggregate;
16
use loophp\iterators\IterableIteratorAggregate;
17
use loophp\iterators\ResourceIteratorAggregate;
18
use loophp\iterators\StringIteratorAggregate;
19
use NoRewindIterator;
20
use Psr\Cache\CacheItemPoolInterface;
21
use Symfony\Component\Cache\Adapter\ArrayAdapter;
22
use Traversable;
23
24
use const INF;
25
use const PHP_INT_MAX;
26
27
/**
28
 * @immutable
29
 *
30
 * @template TKey
31
 * @template T
32
 *
33
 * @implements \loophp\collection\Contract\Collection<TKey, T>
34
 */
35
final class Collection implements CollectionInterface, JsonSerializable, Countable
36
{
37
    /**
38
     * @var ClosureIteratorAggregate<TKey, T>
39
     */
40
    private ClosureIteratorAggregate $innerIterator;
41
42
    /**
43
     * @param callable(mixed ...$parameters): iterable<TKey, T> $callable
44
     * @param iterable<int, mixed> $parameters
45
     */
46 709
    private function __construct(callable $callable, iterable $parameters = [])
47
    {
48 709
        $this->innerIterator = new ClosureIteratorAggregate($callable, $parameters);
49
    }
50
51 21
    public function all(bool $normalize = true): array
52
    {
53 21
        return iterator_to_array((new Operation\All())()($normalize)($this));
54
    }
55
56 2
    public function append(mixed ...$items): CollectionInterface
57
    {
58 2
        return new self((new Operation\Append())()($items), [$this]);
59
    }
60
61 4
    public function apply(callable ...$callbacks): CollectionInterface
62
    {
63 4
        return new self((new Operation\Apply())()(...$callbacks), [$this]);
64
    }
65
66 4
    public function associate(
67
        ?callable $callbackForKeys = null,
68
        ?callable $callbackForValues = null
69
    ): CollectionInterface {
70 4
        $defaultCallback = static fn (mixed $carry): mixed => $carry;
71
72 4
        return new self((new Operation\Associate())()($callbackForKeys ?? $defaultCallback)($callbackForValues ?? $defaultCallback), [$this]);
73
    }
74
75 2
    public function asyncMap(callable $callback): CollectionInterface
76
    {
77 2
        return new self((new Operation\AsyncMap())()($callback), [$this]);
78
    }
79
80 2
    public function asyncMapN(callable ...$callbacks): CollectionInterface
81
    {
82 2
        return new self((new Operation\AsyncMapN())()(...$callbacks), [$this]);
83
    }
84
85 4
    public function averages(): CollectionInterface
86
    {
87 4
        return new self((new Operation\Averages())(), [$this]);
88
    }
89
90 3
    public function cache(?CacheItemPoolInterface $cache = null): CollectionInterface
91
    {
92 3
        return new self((new Operation\Cache())()($cache ?? new ArrayAdapter()), [$this]);
93
    }
94
95 8
    public function chunk(int ...$sizes): CollectionInterface
96
    {
97 8
        return new self((new Operation\Chunk())()(...$sizes), [$this]);
98
    }
99
100 4
    public function coalesce(): CollectionInterface
101
    {
102 4
        return new self((new Operation\Coalesce())(), [$this]);
103
    }
104
105 4
    public function collapse(): CollectionInterface
106
    {
107 4
        return new self((new Operation\Collapse())(), [$this]);
108
    }
109
110 6
    public function column(mixed $column): CollectionInterface
111
    {
112 6
        return new self((new Operation\Column())()($column), [$this]);
113
    }
114
115 6
    public function combinate(?int $length = null): CollectionInterface
116
    {
117 6
        return new self((new Operation\Combinate())()($length), [$this]);
118
    }
119
120 6
    public function combine(mixed ...$keys): CollectionInterface
121
    {
122 6
        return new self((new Operation\Combine())()($keys), [$this]);
123
    }
124
125 4
    public function compact(mixed ...$values): CollectionInterface
126
    {
127 4
        return new self((new Operation\Compact())()($values), [$this]);
128
    }
129
130 10
    public function compare(callable $comparator, $default = null)
131
    {
132 10
        return (new self((new Operation\Compare())()($comparator), [$this]))->current(0, $default);
133
    }
134
135 10
    public function contains(mixed ...$values): bool
136
    {
137 10
        return (new Operation\Contains())()($values)($this)->current();
138
    }
139
140 8
    public function count(): int
141
    {
142 8
        return iterator_count($this);
143
    }
144
145 2
    public function countIn(int &$counter): CollectionInterface
146
    {
147 2
        return new self(
148 2
            (new Operation\Apply())()(
149 2
                static function () use (&$counter): void {
150 1
                    ++$counter;
151 2
                }
152 2
            ),
153 2
            [$this]
154 2
        );
155
    }
156
157 97
    public function current(int $index = 0, $default = null)
158
    {
159 97
        return (new Operation\Current())()($index)($default)($this)->current();
160
    }
161
162 4
    public function cycle(): CollectionInterface
163
    {
164 4
        return new self((new Operation\Cycle())(), [$this]);
165
    }
166
167 14
    public function diff(mixed ...$values): CollectionInterface
168
    {
169 14
        return new self((new Operation\Diff())()($values), [$this]);
170
    }
171
172 4
    public function diffKeys(mixed ...$keys): CollectionInterface
173
    {
174 4
        return new self((new Operation\DiffKeys())()($keys), [$this]);
175
    }
176
177 12
    public function distinct(?callable $comparatorCallback = null, ?callable $accessorCallback = null): CollectionInterface
178
    {
179 12
        $accessorCallback ??=
180
            /**
181
             * @param T $value
0 ignored issues
show
Bug introduced by
The type loophp\collection\T was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
182
             * @param TKey $key
0 ignored issues
show
Bug introduced by
The type loophp\collection\TKey was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
183
             *
184
             * @return T
185
             */
186 12
            static fn (mixed $value, mixed $key): mixed => $value;
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

186
            static fn (mixed $value, /** @scrutinizer ignore-unused */ mixed $key): mixed => $value;

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
187
188 12
        $comparatorCallback ??=
189
            /**
190
             * @param T $left
191
             *
192
             * @return Closure(T): bool
193
             */
194 12
            static fn (mixed $left): Closure =>
195
                /**
196
                 * @param T $right
197
                 */
198 8
                static fn (mixed $right): bool => $left === $right;
199
200 12
        return new self((new Operation\Distinct())()($comparatorCallback)($accessorCallback), [$this]);
201
    }
202
203 4
    public function drop(int $count): CollectionInterface
204
    {
205 4
        return new self((new Operation\Drop())()($count), [$this]);
206
    }
207
208 4
    public function dropWhile(callable ...$callbacks): CollectionInterface
209
    {
210 4
        return new self((new Operation\DropWhile())()(...$callbacks), [$this]);
211
    }
212
213 4
    public function dump(string $name = '', int $size = 1, ?Closure $closure = null): CollectionInterface
214
    {
215 4
        return new self((new Operation\Dump())()($name)($size)($closure), [$this]);
216
    }
217
218 10
    public function duplicate(?callable $comparatorCallback = null, ?callable $accessorCallback = null): CollectionInterface
219
    {
220 10
        $accessorCallback ??=
221
            /**
222
             * @param T $value
223
             * @param TKey $key
224
             *
225
             * @return T
226
             */
227 10
            static fn (mixed $value, mixed $key): mixed => $value;
0 ignored issues
show
Unused Code introduced by
The parameter $key is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

227
            static fn (mixed $value, /** @scrutinizer ignore-unused */ mixed $key): mixed => $value;

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
228
229 10
        $comparatorCallback ??=
230
            /**
231
             * @param T $left
232
             *
233
             * @return Closure(T): bool
234
             */
235 10
            static fn (mixed $left): Closure =>
236
                /**
237
                 * @param T $right
238
                 */
239 6
                static fn (mixed $right): bool => $left === $right;
240
241 10
        return new self((new Operation\Duplicate())()($comparatorCallback)($accessorCallback), [$this]);
242
    }
243
244
    /**
245
     * @template UKey
246
     * @template U
247
     *
248
     * @return self<UKey, U>
249
     */
250 4
    public static function empty(): CollectionInterface
251
    {
252 4
        return self::fromIterable([]);
253
    }
254
255 36
    public function equals(iterable $other): bool
256
    {
257 36
        return (new Operation\Equals())()($other)($this)->current();
258
    }
259
260 16
    public function every(callable ...$callbacks): bool
261
    {
262 16
        return (new Operation\Every())()(static fn (int $index, mixed $value, mixed $key, iterable $iterable): bool => CallbacksArrayReducer::or()($callbacks)($value, $key, $iterable))($this)
263 16
            ->current();
264
    }
265
266 2
    public function explode(mixed ...$explodes): CollectionInterface
267
    {
268 2
        return new self((new Operation\Explode())()($explodes), [$this]);
269
    }
270
271 8
    public function falsy(): bool
272
    {
273 8
        return (new Operation\Falsy())()($this)->current();
274
    }
275
276 8
    public function filter(callable ...$callbacks): CollectionInterface
277
    {
278 8
        return new self((new Operation\Filter())()(...$callbacks), [$this]);
279
    }
280
281 10
    public function find(mixed $default = null, callable ...$callbacks)
282
    {
283 10
        return (new Operation\Find())()($default)(...$callbacks)($this)->current();
284
    }
285
286 10
    public function first(mixed $default = null)
287
    {
288 10
        return (new self((new Operation\First())(), [$this]))->current(0, $default);
289
    }
290
291 14
    public function flatMap(callable $callback): CollectionInterface
292
    {
293 14
        return new self((new Operation\FlatMap())()($callback), [$this]);
294
    }
295
296 6
    public function flatten(int $depth = PHP_INT_MAX): CollectionInterface
297
    {
298 6
        return new self((new Operation\Flatten())()($depth), [$this]);
299
    }
300
301 4
    public function flip(): CollectionInterface
302
    {
303 4
        return new self((new Operation\Flip())(), [$this]);
304
    }
305
306 8
    public function foldLeft(callable $callback, mixed $initial)
307
    {
308 8
        return (new self((new Operation\FoldLeft())()($callback)($initial), [$this]))->current();
309
    }
310
311 4
    public function foldLeft1(callable $callback): mixed
312
    {
313 4
        return (new self((new Operation\FoldLeft1())()($callback), [$this]))->current();
314
    }
315
316 2
    public function foldRight(callable $callback, mixed $initial): mixed
317
    {
318 2
        return (new self((new Operation\FoldRight())()($callback)($initial), [$this]))->current();
319
    }
320
321 4
    public function foldRight1(callable $callback): mixed
322
    {
323 4
        return (new self((new Operation\FoldRight1())()($callback), [$this]))->current();
324
    }
325
326 2
    public function forget(mixed ...$keys): CollectionInterface
327
    {
328 2
        return new self((new Operation\Forget())()($keys), [$this]);
329
    }
330
331 2
    public function frequency(): CollectionInterface
332
    {
333 2
        return new self((new Operation\Frequency())(), [$this]);
334
    }
335
336
    /**
337
     * @template NewTKey
338
     * @template NewT
339
     *
340
     * @param callable(mixed ...$parameters): iterable<NewTKey, NewT> $callable
341
     * @param iterable<int, mixed> $parameters
342
     *
343
     * @return self<NewTKey, NewT>
344
     */
345 3
    public static function fromCallable(callable $callable, iterable $parameters = []): CollectionInterface
346
    {
347 3
        return new self($callable, $parameters);
348
    }
349
350
    /**
351
     * @param null|non-negative-int $length
0 ignored issues
show
Documentation Bug introduced by
The doc comment null|non-negative-int at position 2 could not be parsed: Unknown type name 'non-negative-int' at position 2 in null|non-negative-int.
Loading history...
352
     *
353
     * @return self<int, string>
354
     */
355 2
    public static function fromFile(string $filepath, ?int $length = 2): CollectionInterface
356
    {
357 2
        return new self(
358 2
            static fn (): Generator => yield from new ResourceIteratorAggregate(fopen($filepath, 'rb'), true, $length),
359 2
        );
360
    }
361
362
    /**
363
     * @template NewTKey
364
     * @template NewT
365
     *
366
     * @param Generator<NewTKey, NewT> $generator
367
     *
368
     * @return self<NewTKey, NewT>
369
     */
370 2
    public static function fromGenerator(Generator $generator): CollectionInterface
371
    {
372 2
        return new self(static fn (): Generator => yield from new NoRewindIterator($generator));
373
    }
374
375
    /**
376
     * @template UKey
377
     * @template U
378
     *
379
     * @param iterable<UKey, U> $iterable
380
     *
381
     * @return self<UKey, U>
382
     */
383 692
    public static function fromIterable(iterable $iterable): CollectionInterface
384
    {
385 692
        return new self(static fn (): Generator => yield from new IterableIteratorAggregate($iterable));
386
    }
387
388
    /**
389
     * @param resource $resource
390
     *
391
     * @return self<int, string>
392
     */
393 2
    public static function fromResource($resource): CollectionInterface
394
    {
395 2
        return new self(static fn (): Generator => yield from new ResourceIteratorAggregate($resource));
396
    }
397
398
    /**
399
     * @return self<int, string>
400
     */
401 2
    public static function fromString(string $string, string $delimiter = ''): CollectionInterface
402
    {
403 2
        return new self(static fn (): Generator => yield from new StringIteratorAggregate($string, $delimiter));
404
    }
405
406 5
    public function get(mixed $key, mixed $default = null)
407
    {
408 5
        return (new self((new Operation\Get())()($key)($default), [$this]))->current(0, $default);
409
    }
410
411
    /**
412
     * @return Traversable<TKey, T>
413
     */
414 709
    public function getIterator(): Traversable
415
    {
416 709
        yield from $this->innerIterator->getIterator();
417
    }
418
419 6
    public function group(): CollectionInterface
420
    {
421 6
        return new self((new Operation\Group())(), [$this]);
422
    }
423
424 4
    public function groupBy(callable $callback): CollectionInterface
425
    {
426 4
        return new self((new Operation\GroupBy())()($callback), [$this]);
427
    }
428
429 16
    public function has(callable ...$callbacks): bool
430
    {
431 16
        return (new Operation\Has())()(...$callbacks)($this)->current();
432
    }
433
434 6
    public function head(mixed $default = null)
435
    {
436 6
        return (new self((new Operation\Head())(), [$this]))->current(0, $default);
437
    }
438
439 4
    public function ifThenElse(callable $condition, callable $then, ?callable $else = null): CollectionInterface
440
    {
441 4
        $identity =
442
            /**
443
             * @param T $value
444
             *
445
             * @return T
446
             */
447 4
            static fn (mixed $value): mixed => $value;
448
449 4
        return new self((new Operation\IfThenElse())()($condition)($then)($else ?? $identity), [$this]);
450
    }
451
452 6
    public function implode(string $glue = ''): string
453
    {
454 6
        return (new self((new Operation\Implode())()($glue), [$this]))->current(0, '');
455
    }
456
457 4
    public function init(): CollectionInterface
458
    {
459 4
        return new self((new Operation\Init())(), [$this]);
460
    }
461
462 4
    public function inits(): CollectionInterface
463
    {
464 4
        return new self((new Operation\Inits())(), [$this]);
465
    }
466
467 4
    public function intersect(mixed ...$values): CollectionInterface
468
    {
469 4
        return new self((new Operation\Intersect())()($values), [$this]);
470
    }
471
472 6
    public function intersectKeys(mixed ...$keys): CollectionInterface
473
    {
474 6
        return new self((new Operation\IntersectKeys())()($keys), [$this]);
475
    }
476
477 10
    public function intersperse(mixed $element, int $every = 1, int $startAt = 0): CollectionInterface
478
    {
479 10
        return new self((new Operation\Intersperse())()($element)($every)($startAt), [$this]);
480
    }
481
482 14
    public function isEmpty(): bool
483
    {
484 14
        return (new Operation\IsEmpty())()($this)->current();
485
    }
486
487 14
    public function isNotEmpty(): bool
488
    {
489 14
        return (new Operation\IsNotEmpty())()($this)->current();
490
    }
491
492
    /**
493
     * @return array<mixed>
494
     */
495 1
    public function jsonSerialize(): array
496
    {
497 1
        return $this->all(false);
498
    }
499
500 6
    public function key(int $index = 0)
501
    {
502 6
        return (new Operation\Key())()($index)($this)->current();
503
    }
504
505 2
    public function keys(): CollectionInterface
506
    {
507 2
        return new self((new Operation\Keys())(), [$this]);
508
    }
509
510 14
    public function last(mixed $default = null)
511
    {
512 14
        return (new self((new Operation\Last())(), [$this]))->current(0, $default);
513
    }
514
515 12
    public function limit(int $count = -1, int $offset = 0): CollectionInterface
516
    {
517 12
        return new self((new Operation\Limit())()($count)($offset), [$this]);
518
    }
519
520 2
    public function lines(): CollectionInterface
521
    {
522 2
        return new self((new Operation\Lines())(), [$this]);
523
    }
524
525 10
    public function map(callable $callback): CollectionInterface
526
    {
527 10
        return new self((new Operation\Map())()($callback), [$this]);
528
    }
529
530 4
    public function mapN(callable ...$callbacks): CollectionInterface
531
    {
532 4
        return new self((new Operation\MapN())()(...$callbacks), [$this]);
533
    }
534
535 6
    public function match(callable $callback, ?callable $matcher = null): bool
536
    {
537 6
        return (new Operation\MatchOne())()($matcher ?? static fn (): bool => true)($callback)($this)->current();
538
    }
539
540 2
    public function matching(Criteria $criteria): CollectionInterface
541
    {
542 2
        return new self((new Operation\Matching())()($criteria), [$this]);
543
    }
544
545 8
    public function max(mixed $default = null)
546
    {
547 8
        return (new self((new Operation\Max())(), [$this]))->current(0, $default);
548
    }
549
550 2
    public function merge(iterable ...$sources): CollectionInterface
551
    {
552 2
        return new self((new Operation\Merge())()(...$sources), [$this]);
553
    }
554
555 8
    public function min(mixed $default = null)
556
    {
557 8
        return (new self((new Operation\Min())(), [$this]))->current(0, $default);
558
    }
559
560 6
    public function normalize(): CollectionInterface
561
    {
562 6
        return new self((new Operation\Normalize())(), [$this]);
563
    }
564
565 4
    public function nth(int $step, int $offset = 0): CollectionInterface
566
    {
567 4
        return new self((new Operation\Nth())()($step)($offset), [$this]);
568
    }
569
570 8
    public function nullsy(): bool
571
    {
572 8
        return (new Operation\Nullsy())()($this)->current();
573
    }
574
575 6
    public function pack(): CollectionInterface
576
    {
577 6
        return new self((new Operation\Pack())(), [$this]);
578
    }
579
580 2
    public function pad(int $size, mixed $value): CollectionInterface
581
    {
582 2
        return new self((new Operation\Pad())()($size)($value), [$this]);
583
    }
584
585 4
    public function pair(): CollectionInterface
586
    {
587 4
        return new self((new Operation\Pair())(), [$this]);
588
    }
589
590 2
    public function partition(callable ...$callbacks): CollectionInterface
591
    {
592 2
        return (new self((new Operation\Partition())()(...$callbacks), [$this]))
593 2
            ->map(
594
                /**
595
                 * @param iterable<TKey, T> $iterable
596
                 *
597
                 * @return Collection<TKey, T>
598
                 */
599 2
                static fn (iterable $iterable): Collection => Collection::fromIterable($iterable)
600 2
            );
601
    }
602
603 2
    public function permutate(): CollectionInterface
604
    {
605 2
        return new self((new Operation\Permutate())(), [$this]);
606
    }
607
608 2
    public function pipe(callable ...$callbacks): CollectionInterface
609
    {
610 2
        return new self((new Operation\Pipe())()(...$callbacks), [$this]);
611
    }
612
613 12
    public function pluck(mixed $pluck, mixed $default = null): CollectionInterface
614
    {
615 12
        return new self((new Operation\Pluck())()($pluck)($default), [$this]);
616
    }
617
618 2
    public function prepend(mixed ...$items): CollectionInterface
619
    {
620 2
        return new self((new Operation\Prepend())()($items), [$this]);
621
    }
622
623 4
    public function product(iterable ...$iterables): CollectionInterface
624
    {
625 4
        return new self((new Operation\Product())()(...$iterables), [$this]);
626
    }
627
628 2
    public function random(int $size = 1, ?int $seed = null): CollectionInterface
629
    {
630 2
        return new self((new Operation\Random())()($seed ?? random_int(0, 1000))($size), [$this]);
631
    }
632
633
    /**
634
     * @return self<int, float>
635
     */
636 2
    public static function range(float $start = 0.0, float $end = INF, float $step = 1.0): CollectionInterface
637
    {
638 2
        return new self((new Operation\Range())()($start)($end)($step));
639
    }
640
641 6
    public function reduce(callable $callback, mixed $initial = null)
642
    {
643 6
        return (new self((new Operation\Reduce())()($callback)($initial), [$this]))->current();
644
    }
645
646 2
    public function reduction(callable $callback, mixed $initial = null): CollectionInterface
647
    {
648 2
        return new self((new Operation\Reduction())()($callback)($initial), [$this]);
649
    }
650
651 8
    public function reject(callable ...$callbacks): CollectionInterface
652
    {
653 8
        return new self((new Operation\Reject())()(...$callbacks), [$this]);
654
    }
655
656 4
    public function reverse(): CollectionInterface
657
    {
658 4
        return new self((new Operation\Reverse())(), [$this]);
659
    }
660
661 2
    public function rsample(float $probability): CollectionInterface
662
    {
663 2
        return new self((new Operation\RSample())()($probability), [$this]);
664
    }
665
666 46
    public function same(iterable $other, ?callable $comparatorCallback = null): bool
667
    {
668 46
        $comparatorCallback ??=
669
            /**
670
             * @param T $leftValue
671
             * @param TKey $leftKey
672
             *
673
             * @return Closure(T, TKey): bool
674
             */
675 46
            static fn (mixed $leftValue, mixed $leftKey): Closure =>
676
                /**
677
                 * @param T $rightValue
678
                 * @param TKey $rightKey
679
                 */
680 32
                static fn (mixed $rightValue, mixed $rightKey): bool => $leftValue === $rightValue && $leftKey === $rightKey;
681
682 46
        return (new Operation\Same())()($other)($comparatorCallback)($this)->current();
683
    }
684
685 2
    public function scale(
686
        float $lowerBound,
687
        float $upperBound,
688
        float $wantedLowerBound = 0.0,
689
        float $wantedUpperBound = 1.0,
690
        float $base = 0.0
691
    ): CollectionInterface {
692 2
        return new self((new Operation\Scale())()($lowerBound)($upperBound)($wantedLowerBound)($wantedUpperBound)($base), [$this]);
693
    }
694
695 4
    public function scanLeft(callable $callback, mixed $initial): CollectionInterface
696
    {
697 4
        return new self((new Operation\ScanLeft())()($callback)($initial), [$this]);
698
    }
699
700 6
    public function scanLeft1(callable $callback): CollectionInterface
701
    {
702 6
        return new self((new Operation\ScanLeft1())()($callback), [$this]);
703
    }
704
705 4
    public function scanRight(callable $callback, mixed $initial): CollectionInterface
706
    {
707 4
        return new self((new Operation\ScanRight())()($callback)($initial), [$this]);
708
    }
709
710 4
    public function scanRight1(callable $callback): CollectionInterface
711
    {
712 4
        return new self((new Operation\ScanRight1())()($callback), [$this]);
713
    }
714
715 2
    public function shuffle(?int $seed = null): CollectionInterface
716
    {
717 2
        return new self((new Operation\Shuffle())()($seed ?? random_int(0, 1000)), [$this]);
718
    }
719
720 8
    public function since(callable ...$callbacks): CollectionInterface
721
    {
722 8
        return new self((new Operation\Since())()(...$callbacks), [$this]);
723
    }
724
725 6
    public function slice(int $offset, int $length = -1): CollectionInterface
726
    {
727 6
        return new self((new Operation\Slice())()($offset)($length), [$this]);
728
    }
729
730 12
    public function sort(int $type = OperationInterface\Sortable::BY_VALUES, ?callable $callback = null): CollectionInterface
731
    {
732 12
        return new self((new Operation\Sort())()($type)($callback), [$this]);
733
    }
734
735 2
    public function span(callable ...$callbacks): CollectionInterface
736
    {
737 2
        return (new self((new Operation\Span())()(...$callbacks), [$this]))
738 2
            ->map(
739
                /**
740
                 * @param iterable<TKey, T> $iterable
741
                 *
742
                 * @return Collection<TKey, T>
743
                 */
744 2
                static fn (iterable $iterable): Collection => Collection::fromIterable($iterable)
745 2
            );
746
    }
747
748 6
    public function split(int $type = OperationInterface\Splitable::BEFORE, callable ...$callbacks): CollectionInterface
749
    {
750 6
        return new self((new Operation\Split())()($type)(...$callbacks), [$this]);
751
    }
752
753 4
    public function squash(): CollectionInterface
754
    {
755 4
        return self::fromIterable($this->pack()->all(false))->unpack();
756
    }
757
758 4
    public function strict(?callable $callback = null): CollectionInterface
759
    {
760 4
        return new self((new Operation\Strict())()($callback), [$this]);
761
    }
762
763 2
    public function tail(): CollectionInterface
764
    {
765 2
        return new self((new Operation\Tail())(), [$this]);
766
    }
767
768 4
    public function tails(): CollectionInterface
769
    {
770 4
        return new self((new Operation\Tails())(), [$this]);
771
    }
772
773 6
    public function takeWhile(callable ...$callbacks): CollectionInterface
774
    {
775 6
        return new self((new Operation\TakeWhile())()(...$callbacks), [$this]);
776
    }
777
778
    /**
779
     * @template U
780
     *
781
     * @param callable(int): U $callback
782
     *
783
     * @return self<int, U>
784
     */
785 2
    public static function times(int $number = 0, ?callable $callback = null): CollectionInterface
786
    {
787 2
        return new self((new Operation\Times())()($number)($callback));
788
    }
789
790 2
    public function transpose(): CollectionInterface
791
    {
792 2
        return new self((new Operation\Transpose())(), [$this]);
793
    }
794
795 8
    public function truthy(): bool
796
    {
797 8
        return (new Operation\Truthy())()($this)->current();
798
    }
799
800 2
    public static function unfold(callable $callback, iterable $parameters = []): CollectionInterface
801
    {
802 2
        return new self((new Operation\Unfold())()($parameters)($callback));
803
    }
804
805 2
    public function unlines(): string
806
    {
807 2
        return (new self((new Operation\Unlines())(), [$this]))->current(0, '');
808
    }
809
810 4
    public function unpack(): CollectionInterface
811
    {
812 4
        return new self((new Operation\Unpack())(), [$this]);
813
    }
814
815 2
    public function unpair(): CollectionInterface
816
    {
817 2
        return new self((new Operation\Unpair())(), [$this]);
818
    }
819
820 4
    public function until(callable ...$callbacks): CollectionInterface
821
    {
822 4
        return new self((new Operation\Until())()(...$callbacks), [$this]);
823
    }
824
825 2
    public function unwindow(): CollectionInterface
826
    {
827 2
        return new self((new Operation\Unwindow())(), [$this]);
828
    }
829
830 2
    public function unwords(): string
831
    {
832 2
        return (new self((new Operation\Unwords())(), [$this]))->current(0, '');
833
    }
834
835 6
    public function unwrap(): CollectionInterface
836
    {
837 6
        return new self((new Operation\Unwrap())(), [$this]);
838
    }
839
840 2
    public function unzip(): CollectionInterface
841
    {
842 2
        return new self((new Operation\Unzip())(), [$this]);
843
    }
844
845 4
    public function when(callable $predicate, callable $whenTrue, ?callable $whenFalse = null): CollectionInterface
846
    {
847 4
        $whenFalse ??=
848
            /**
849
             * @param iterable<TKey, T> $iterable
850
             *
851
             * @return iterable<TKey, T>
852
             */
853 4
            static fn (iterable $iterable): iterable => $iterable;
854
855 4
        return new self((new Operation\When())()($predicate)($whenTrue)($whenFalse), [$this]);
856
    }
857
858 8
    public function window(int $size): CollectionInterface
859
    {
860 8
        return new self((new Operation\Window())()($size), [$this]);
861
    }
862
863 2
    public function words(): CollectionInterface
864
    {
865 2
        return new self((new Operation\Words())(), [$this]);
866
    }
867
868 4
    public function wrap(): CollectionInterface
869
    {
870 4
        return new self((new Operation\Wrap())(), [$this]);
871
    }
872
873 4
    public function zip(iterable ...$iterables): CollectionInterface
874
    {
875 4
        return new self((new Operation\Zip())()(...$iterables), [$this]);
876
    }
877
}
878