Passed
Branch master (fb2e38)
by Sebastian
02:23
created

ArrayListTrait::forEach()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 3
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 4
ccs 3
cts 3
cp 1
crap 2
rs 10
1
<?php
2
declare(strict_types=1);
3
/*
4
 * Copyright (C) 2018 Sebastian Böttger <[email protected]>
5
 * You may use, distribute and modify this code under the
6
 * terms of the MIT license.
7
 *
8
 * You should have received a copy of the MIT license with
9
 * this file. If not, please visit: https://opensource.org/licenses/mit-license.php
10
 */
11
12
namespace Seboettg\Collection\Lists;
13
14
use Seboettg\Collection\Comparable\Comparable;
15
use Seboettg\Collection\Lists\ListFeatures\ListAccessTrait;
16
use Seboettg\Collection\Lists\ListFeatures\ListOperationsTrait;
17
use Seboettg\Collection\Lists\MapFeatures\MapFeaturesTrait;
18
use Seboettg\Collection\NativePhp\IteratorTrait;
19
use function Seboettg\Collection\Assert\assertComparable;
20
use function Seboettg\Collection\Assert\assertStringable;
21
use function Seboettg\Collection\Common\isComparable;
22
use function Seboettg\Collection\Common\isScalarOrStringable;
23
use function Seboettg\Collection\Common\in_array;
24
use function Seboettg\Collection\Common\strval;
25
26
/**
27
 * @property array $array Base array of this data structure
28
 */
29
trait ArrayListTrait
30
{
31
    use ListAccessTrait,
32
        IteratorTrait,
33
        ListOperationsTrait,
34
        MapFeaturesTrait;
35
36
    /**
37
     * flush array list
38
     *
39
     * @return ListInterface|ArrayListTrait
40
     */
41 1
    public function clear(): void
42
    {
43 1
        unset($this->array);
44 1
        $this->array = [];
45 1
    }
46
47
    /**
48
     * Adds the specified element to the end of this list.
49
     *
50
     * @param mixed $element
51
     */
52 27
    public function add($element): void
53
    {
54 27
        end($this->array);
55 27
        $this->array[] = $element;
56 27
    }
57
58
    /**
59
     * @inheritDoc
60
     */
61 3
    public function addAll(iterable $elements): void
62
    {
63 3
        foreach ($elements as $element) {
64 3
            $this->add($element);
65
        }
66 3
    }
67
68
    /**
69
     * @inheritDoc
70
     */
71 1
    public function remove($key): void
72
    {
73 1
        unset($this->array[$key]);
74 1
    }
75
76
    /**
77
     * {@inheritdoc}
78
     */
79 9
    public function contains($value): bool
80
    {
81
        if (
82 9
            isScalarOrStringable($value) /* && $this->all(fn($item) => isScalarOrStringable($item))) */ ||
83
            isComparable($value) /* && $this->all(fn($item) => isComparable($item))) */
84
        ) {
85
            // use custom in_array function
86 8
            return in_array($value, $this->array) !== false;
87
        } else {
88
            // use PHP's native \in_array function
89 1
            return \in_array(
90 1
                print_r($value, true),
91 1
                array_map(fn($item): string => print_r($item, true), $this->array)
92
            );
93
        }
94
    }
95
96
    /**
97
     * @inheritDoc
98
     */
99 1
    public function shuffle(): ListInterface
100
    {
101 1
        $array = $this->array;
102 1
        shuffle($array);
103 1
        return listFromArray($array);
104
    }
105
106
    /**
107
     * @inheritDoc
108
     */
109 12
    public function filter(?callable $predicate = null, bool $preserveKeys = false): ListInterface
110
    {
111 12
        $list = emptyList();
112 12
        $filtered = $predicate == null ? array_filter($this->array) : array_filter($this->array, $predicate);
113 12
        $list->setArray(
114 12
            $preserveKeys ? $filtered : array_values($filtered)
115
        );
116 12
        return $list;
117
    }
118
119
    /**
120
     * @param array $array
121
     */
122 59
    public function setArray(array $array): void
123
    {
124 59
        $this->replace($array);
125 59
    }
126
127
    /**
128
     * @param array $data
129
     */
130 59
    public function replace(array $data): void
131
    {
132 59
        $this->array = $data;
133 59
    }
134
135
    /**
136
     * returns a new ArrayList containing all the elements of this ArrayList after applying the callback function to each one.
137
     * @param callable $mapFunction
138
     * @return ListInterface|ArrayListTrait
139
     */
140 9
    public function map(callable $mapFunction): ListInterface
141
    {
142 9
        $list = emptyList();
143 9
        foreach ($this as $value) {
144 9
            $list->add($mapFunction($value));
145
        }
146 8
        return $list;
147
    }
148
149
    /**
150
     * @inheritDoc
151
     * @param callable $mapFunction
152
     * @return ListInterface
153
     */
154 1
    public function mapNotNull(callable $mapFunction): ListInterface
155
    {
156 1
        $list = $this->map($mapFunction);
157 1
        return $list->filter();
158
    }
159
160
    /**
161
     * Returns a new ArrayList containing a one-dimensional array of all elements of this ArrayList. Keys are going lost.
162
     * @return ListInterface
163
     */
164 1
    public function flatten(): ListInterface
165
    {
166 1
        $flattenedArray = [];
167
        array_walk_recursive($this->array, function ($item) use (&$flattenedArray) {
168 1
            $flattenedArray[] = $item;
169 1
        });
170 1
        return listOf(...$flattenedArray);
171
    }
172
173
    /**
174
     * @inheritDoc
175
     * @param callable $collectFunction
176
     * @return mixed
177
     */
178 1
    public function collect(callable $collectFunction)
179
    {
180 1
        return $collectFunction($this->array);
181
    }
182
183
    /**
184
     * @inheritDoc
185
     */
186 6
    public function joinToString(string $delimiter, string $prefix = null, string $suffix = null): string
187
    {
188
        $result = implode($delimiter, $this->map(function ($item) {
189 6
            assertStringable(
190 6
                $item,
191 6
                "All elements in the list must be convertible to string in order to use joinToString."
192
            );
193 5
            return strval($item);
194 6
        })->toArray());
195 5
        if ($prefix !== null) {
196 1
            $result = $prefix . $result;
197
        }
198 5
        if ($suffix !== null) {
199 2
            $result = $result . $suffix;
200
        }
201 5
        return $result;
202
    }
203
204
    /**
205
     * @inheritDoc
206
     * @deprecated use joinToString instead
207
     */
208 1
    public function collectToString(string $delimiter): string
209
    {
210 1
        return $this->joinToString($delimiter);
211
    }
212
213
    /**
214
     * @inheritDoc
215
     * @return int
216
     */
217 20
    public function count(): int
218
    {
219 20
        return count($this->array);
220
    }
221
222
    /**
223
     * @inheritDoc
224
     */
225 1
    public function size(): int
226
    {
227 1
        return $this->count();
228
    }
229
230 2
    public function any(callable $predicate): bool
231
    {
232 2
        return $this->filter($predicate)->count() > 0;
233
    }
234
235 4
    public function all(callable $predicate): bool
236
    {
237 4
        return $this->count() === $this->filter($predicate)->count();
238
    }
239
240
    /**
241
     * @inheritDoc
242
     */
243 2
    public function chunk(int $size): ListInterface
244
    {
245 2
        $listOfChunks = emptyList();
246 2
        $arrayChunks = array_chunk($this->array, $size);
247 2
        foreach ($arrayChunks as $arrayChunk) {
248 2
            $listOfChunks->add(listOf(...$arrayChunk));
249
        }
250 2
        return $listOfChunks;
251
    }
252
253 2
    public function distinct(): ListInterface
254
    {
255
256 2
        if ($this->all(fn($item): bool => isScalarOrStringable($item))) {
257 1
            return listFromArray(array_unique($this->toArray()));
258
        } else {
259 1
            $newList = emptyList();
260 1
            $values = $this->array;
261 1
            foreach ($values as $value) {
262 1
                if (!$newList->contains($value)) {
263 1
                    $newList->add($value);
264
                }
265
            }
266 1
            return $newList;
267
        }
268
    }
269
270
    /**
271
     * @inheritDoc
272
     */
273 7
    public function forEach(callable $action): void
274
    {
275 7
        foreach ($this->array as $element) {
276 7
            $action($element);
277
        }
278 7
    }
279
280
    /**
281
     * @inheritDoc
282
     */
283 2
    public function getOrElse(int $index, callable $defaultValue)
284
    {
285 2
        if (array_key_exists($index, $this->array)) {
286 1
            return $this->array[$index];
287
        }
288 1
        return $defaultValue($this);
289
    }
290
291
    /**
292
     * @inheritDoc
293
     * @param int $fromIndex
294
     * @param int $toIndex
295
     * @return ListInterface
296
     */
297 1
    public function subList(int $fromIndex, int $toIndex): ListInterface
298
    {
299 1
        $list = emptyList();
300 1
        for ($i = $fromIndex; $i < $toIndex; ++$i) {
301 1
            if (isset($this->array[$i])) {
302 1
                $list->add($this->array[$i]);
303
            }
304
        }
305 1
        return $list;
306
    }
307
308
    /**
309
     * Return first element of this list that matches the matchingCondition. If no element matches the condition, null
310
     * will be returned.
311
     *
312
     * @param callable $matchingCondition
313
     * @return mixed|null
314
     */
315 2
    public function searchBy(callable $matchingCondition)
316
    {
317 2
        $list = listOf(...array_filter($this->array));
318
        return $list
319 2
            ->filter($matchingCondition)
320 2
            ->getOrElse(0, fn() => null);
321
    }
322
323 2
    public function isEmpty(): bool
324
    {
325 2
        return $this->count() === 0;
326
    }
327
328
    /**
329
     * {@inheritDoc}
330
     */
331 12
    public function toArray(): array
332
    {
333 12
        return $this->array;
334
    }
335
}
336