Passed
Pull Request — main (#3)
by Pol
12:56
created

RandomIteratorAggregate   A

Complexity

Total Complexity 6

Size/Duplication

Total Lines 54
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 19
c 1
b 0
f 0
dl 0
loc 54
rs 10
wmc 6

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getIterator() 0 16 4
A __construct() 0 4 1
A predictableRandomArray() 0 7 1
1
<?php
2
3
/**
4
 * For the full copyright and license information, please view
5
 * the LICENSE file that was distributed with this source code.
6
 */
7
8
declare(strict_types=1);
9
10
namespace loophp\iterators;
11
12
use Iterator;
13
use IteratorAggregate;
14
use Traversable;
15
16
use const PHP_INT_MAX;
17
use const PHP_INT_MIN;
18
19
/**
20
 * @template TKey
21
 * @template T
22
 *
23
 * @implements IteratorAggregate<TKey, T>
24
 */
25
final class RandomIteratorAggregate implements IteratorAggregate
26
{
27
    /**
28
     * @var IteratorAggregate<TKey, T>
29
     */
30
    private IteratorAggregate $iteratorAggregate;
31
32
    private int $seed;
33
34
    /**
35
     * @param Iterator<TKey, T> $iterator
36
     */
37
    public function __construct(Iterator $iterator, ?int $seed = null)
38
    {
39
        $this->iteratorAggregate = new CachingIteratorAggregate($iterator);
40
        $this->seed = $seed ?? random_int(PHP_INT_MIN, PHP_INT_MAX);
41
    }
42
43
    /**
44
     * @return Traversable<TKey, T>
45
     */
46
    public function getIterator(): Traversable
47
    {
48
        $indexes = $this->predictableRandomArray(
49
            range(0, iterator_count($this->iteratorAggregate->getIterator()) - 1),
50
            $this->seed
51
        );
52
53
        $i = 0;
54
55
        foreach ($indexes as $index) {
56
            foreach ($this->iteratorAggregate as $k => $v) {
57
                if ($indexes[$index] === $i++) {
58
                    yield $k => $v;
59
                    $i = 0;
60
61
                    continue 2;
62
                }
63
            }
64
        }
65
    }
66
67
    /**
68
     * @param array<int, int> $array
69
     *
70
     * @return array<int, int>
71
     */
72
    private function predictableRandomArray(array $array, int $seed): array
73
    {
74
        mt_srand($seed);
75
        shuffle($array);
76
        mt_srand();
77
78
        return $array;
79
    }
80
}
81