Passed
Push — master ( 904df5...62fce2 )
by Pol
02:08
created

Collection::entropy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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