Passed
Push — master ( 34488c...4ee1ca )
by Maxim
02:53 queued 11s
created

Reorganizers::collapse()   A

Complexity

Conditions 3
Paths 1

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 13
dl 0
loc 19
ccs 12
cts 12
cp 1
rs 9.8333
c 0
b 0
f 0
cc 3
nc 1
nop 0
crap 3
1
<?php
2
/**
3
 * @author Maxim Sokolovsky
4
 */
5
6
namespace WS\Utils\Collections\Functions;
7
8
use Closure;
9
use WS\Utils\Collections\ArrayList;
10
use WS\Utils\Collections\Collection;
11
12
class Reorganizers
13
{
14 17
    private static function collectionConstructor(? array $elements = null): Collection  {
15 17
        return new ArrayList($elements);
16
    }
17
18
    /**
19
     * Returns <Fn($c: Collection): Collection> that shuffles elements
20
     * @return Closure
21
     */
22 5
    public static function shuffle(): Closure
23
    {
24
        return static function (Collection $collection): Collection {
25 5
            $array = $collection->toArray();
26 5
            shuffle($array);
27
28 5
            return self::collectionConstructor($array);
29 5
        };
30
    }
31
32
    /**
33
     * Returns Closure <Fn($c: Collection): Collection> that gets $count random elements from collection
34
     * @param int $count
35
     * @return Closure
36
     */
37 10
    public static function random(int $count = 1): Closure
38
    {
39
        return static function (Collection $collection) use ($count): Collection {
40
            /**
41
             * Collection
42
             */
43 10
            $resultCollection = self::collectionConstructor();
44 10
            if ($count === 0) {
45 2
                return $resultCollection;
46
            }
47
48 8
            $collectionSize = $collection->size();
49 8
            $expectedCount = $count;
50
51 8
            if ($collectionSize < $expectedCount) {
52 2
                return $resultCollection;
53
            }
54
55 6
            $rest = $collectionSize;
56 6
            $generated = 0;
57 6
            $multiplicity = (int)round($collectionSize / $expectedCount);
58
59
            $rangeRandomizer = static function () use ($multiplicity): int {
60 4
                return random_int(0, $multiplicity - 1);
61 6
            };
62
63
            $trier = static function () use (& $generated, & $rest, $expectedCount, $rangeRandomizer): bool {
64 6
                $rest--;
65 6
                if ($generated === $expectedCount) {
66 4
                    return false;
67
                }
68 6
                if ($generated + $rest + 1 <= $expectedCount) {
69 2
                    return true;
70
                }
71 4
                if ($rangeRandomizer() !== 0) {
72
                    return false;
73
                }
74 4
                $generated++;
75 4
                return true;
76 6
            };
77
78
            return $collection
79 6
                ->stream()
80 6
                ->filter($trier)
81 6
                ->getCollection();
82 10
        };
83
    }
84
85
    /**
86
     * Returns Closure <Fn($c: Collection): Collection> that split collection into sub collections with $size
87
     * @param int $size
88
     * @return Closure
89
     */
90 1
    public static function chunk(int $size): Closure
91
    {
92
        return static function (Collection $collection) use ($size): Collection {
93 1
            $chunkCollection = self::collectionConstructor();
94 1
            $currentChunk = self::collectionConstructor();
95 1
            $pointer = $size;
96
            $collection
97 1
                ->stream()
98
                ->each(static function ($el) use ($size, $chunkCollection, & $currentChunk, & $pointer) {
99 1
                    $pointer--;
100 1
                    $currentChunk->add($el);
101
102 1
                    if ($pointer === 0) {
103 1
                        $chunkCollection->add($currentChunk);
104 1
                        $currentChunk = self::collectionConstructor();
105 1
                        $pointer = $size;
106
                    }
107 1
                })
108
            ;
109 1
            return $chunkCollection;
110 1
        };
111
    }
112
113
    /**
114
     * Returns Closure <Fn($c: Collection): Collection> that collapses a collection of arrays into a single, flat collection
115
     * @return Closure
116
     */
117 1
    public static function collapse(): Closure
118
    {
119
        return static function (Collection $collection): Collection {
120
            $flatIterable = static function (iterable $collection) use (& $flatIterable): array  {
121 1
                $res = [];
122 1
                foreach ($collection as $item) {
123 1
                    if (is_iterable($item)) {
124 1
                        $toPush = $flatIterable($item);
125 1
                        array_unshift($toPush, $res);
126 1
                        array_push(...$toPush);
127 1
                        $res = array_shift($toPush);
128
                    } else {
129 1
                        $res[] = $item;
130
                    }
131
                }
132 1
                return $res;
133 1
            };
134
135 1
            return self::collectionConstructor($flatIterable($collection));
136 1
        };
137
    }
138
}
139