GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — develop ( c3b70c...588978 )
by Baptiste
05:12
created

Sequence::of()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 3
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 6
ccs 4
cts 4
cp 1
crap 1
rs 10
1
<?php
2
declare(strict_types = 1);
3
4
namespace Innmind\Immutable;
5
6
use Innmind\Immutable\{
7
    Exception\OutOfBoundException,
8
    Exception\LogicException,
9
    Exception\ElementNotFoundException,
10
    Exception\GroupEmptySequenceException
11
};
12
13
/**
14
 * {@inheritdoc}
15
 */
16
final class Sequence implements \Countable
17
{
18
    private array $values;
19
    private ?int $size;
20
21 182
    public function __construct(...$values)
22
    {
23 182
        $this->values = $values;
24 182
    }
25
26 3
    public static function of(...$values): self
27
    {
28 3
        $self = new self;
29 3
        $self->values = $values;
30
31 3
        return $self;
32
    }
33
34 128
    public function size(): int
35
    {
36 128
        return $this->size ?? $this->size = \count($this->values);
37
    }
38
39
    /**
40
     * {@inheritdoc}
41
     */
42 1
    public function count(): int
43
    {
44 1
        return $this->size();
45
    }
46
47 104
    public function toArray(): array
48
    {
49 104
        return $this->values;
50
    }
51
52
    /**
53
     * Return the element at the given index
54
     *
55
     * @throws OutOfBoundException
56
     *
57
     * @return mixed
58
     */
59 26
    public function get(int $index)
60
    {
61 26
        if (!$this->has($index)) {
62 2
            throw new OutOfBoundException;
63
        }
64
65 24
        return $this->values[$index];
66
    }
67
68
    /**
69
     * Check the index exist
70
     */
71 31
    public function has(int $index): bool
72
    {
73 31
        return \array_key_exists($index, $this->values);
74
    }
75
76
    /**
77
     * Return the diff between this sequence and another
78
     */
79 4
    public function diff(self $seq): self
80
    {
81
        return $this->filter(static function($value) use ($seq): bool {
82 4
            return !$seq->contains($value);
83 4
        });
84
    }
85
86
    /**
87
     * Remove all duplicates from the sequence
88
     */
89 35
    public function distinct(): self
90
    {
91 35
        return $this->reduce(
92 35
            new self,
93
            static function(self $values, $value): self {
94 27
                if ($values->contains($value)) {
95 4
                    return $values;
96
                }
97
98 27
                return $values->add($value);
99 35
            }
100
        );
101
    }
102
103
    /**
104
     * Remove the n first elements
105
     */
106 5
    public function drop(int $size): self
107
    {
108 5
        $self = new self;
109 5
        $self->values = \array_slice($this->values, $size);
110
111 5
        return $self;
112
    }
113
114
    /**
115
     * Remove the n last elements
116
     */
117 2
    public function dropEnd(int $size): self
118
    {
119 2
        $self = new self;
120 2
        $self->values = \array_slice($this->values, 0, $this->size() - $size);
121
122 2
        return $self;
123
    }
124
125
    /**
126
     * Check if the two sequences are equal
127
     */
128 8
    public function equals(self $seq): bool
129
    {
130 8
        return $this->values === $seq->toArray();
131
    }
132
133
    /**
134
     * Return all elements that satisfy the given predicate
135
     *
136
     * @param callable(mixed): bool $predicate
137
     */
138 20
    public function filter(callable $predicate): self
139
    {
140 20
        return new self(...\array_filter(
141 20
            $this->values,
142 20
            $predicate
143
        ));
144
    }
145
146
    /**
147
     * Apply the given function to all elements of the sequence
148
     *
149
     * @param callable(mixed): void $function
150
     */
151 54
    public function foreach(callable $function): void
152
    {
153 54
        foreach ($this->values as $value) {
154 43
            $function($value);
155
        }
156 53
    }
157
158
    /**
159
     * Return a new map of pairs grouped by keys determined with the given
160
     * discriminator function
161
     *
162
     * @param callable(mixed) $discriminator
163
     *
164
     * @return Map<mixed, self>
165
     */
166 2
    public function groupBy(callable $discriminator): Map
167
    {
168 2
        if ($this->size() === 0) {
169 1
            throw new GroupEmptySequenceException;
170
        }
171
172 1
        $map = null;
173
174 1
        foreach ($this->values as $value) {
175 1
            $key = $discriminator($value);
176
177 1
            if ($map === null) {
178 1
                $map = new Map(
179 1
                    Type::determine($key),
180 1
                    self::class
181
                );
182
            }
183
184 1
            if ($map->contains($key)) {
185 1
                $map = $map->put(
186 1
                    $key,
187 1
                    $map->get($key)->add($value)
188
                );
189
            } else {
190 1
                $map = $map->put($key, new self($value));
191
            }
192
        }
193
194 1
        return $map;
1 ignored issue
show
Bug Best Practice introduced by
The expression return $map could return the type null which is incompatible with the type-hinted return Innmind\Immutable\Map. Consider adding an additional type-check to rule them out.
Loading history...
195
    }
196
197
    /**
198
     * Return the first element
199
     *
200
     * @return mixed
201
     */
202 4
    public function first()
203
    {
204 4
        if ($this->size() === 0) {
205 1
            throw new OutOfBoundException;
206
        }
207
208 3
        return $this->values[0];
209
    }
210
211
    /**
212
     * Return the last element
213
     *
214
     * @return mixed
215
     */
216 4
    public function last()
217
    {
218 4
        if ($this->size() === 0) {
219 1
            throw new OutOfBoundException;
220
        }
221
222 3
        return $this->values[$this->size() - 1];
223
    }
224
225
    /**
226
     * Check if the sequence contains the given element
227
     *
228
     * @param mixed $element
229
     */
230 75
    public function contains($element): bool
231
    {
232 75
        return \in_array($element, $this->values, true);
233
    }
234
235
    /**
236
     * Return the index for the given element
237
     *
238
     * @param mixed $element
239
     *
240
     * @throws ElementNotFoundException
241
     */
242 19
    public function indexOf($element): int
243
    {
244 19
        $index = \array_search($element, $this->values, true);
245
246 19
        if ($index === false) {
247 1
            throw new ElementNotFoundException;
248
        }
249
250 18
        return $index;
251
    }
252
253
    /**
254
     * Return the list of indices
255
     *
256
     * @return Stream<int>
257
     */
258 4
    public function indices(): Stream
259
    {
260 4
        if ($this->size() === 0) {
261 2
            return Stream::of('int');
262
        }
263
264 2
        return Stream::of('int', ...\range(0, $this->size() - 1));
265
    }
266
267
    /**
268
     * Return a new sequence by applying the given function to all elements
269
     *
270
     * @param callable(mixed) $function
271
     */
272 4
    public function map(callable $function): self
273
    {
274 4
        $self = clone $this;
275 4
        $self->values = \array_map($function, $this->values);
276
277 4
        return $self;
278
    }
279
280
    /**
281
     * Pad the sequence to a defined size with the given element
282
     *
283
     * @param mixed $element
284
     */
285 2
    public function pad(int $size, $element): self
286
    {
287 2
        $self = new self;
288 2
        $self->values = \array_pad($this->values, $size, $element);
289
290 2
        return $self;
291
    }
292
293
    /**
294
     * Return a sequence of 2 sequences partitioned according to the given predicate
295
     *
296
     * @param callable(mixed): bool $predicate
297
     *
298
     * @return Map<bool, self>
299
     */
300 1
    public function partition(callable $predicate): Map
301
    {
302 1
        $truthy = [];
303 1
        $falsy = [];
304
305 1
        foreach ($this->values as $value) {
306 1
            if ($predicate($value) === true) {
307 1
                $truthy[] = $value;
308
            } else {
309 1
                $falsy[] = $value;
310
            }
311
        }
312
313 1
        $true = new self;
314 1
        $true->values = $truthy;
315 1
        $false = new self;
316 1
        $false->values = $falsy;
317
318 1
        return Map::of('bool', self::class)
319 1
            (true, $true)
320 1
            (false, $false);
321
    }
322
323 13
    public function slice(int $from, int $until): self
324
    {
325 13
        $self = new self;
326 13
        $self->values = \array_slice(
327 13
            $this->values,
328 13
            $from,
329 13
            $until - $from
330
        );
331
332 13
        return $self;
333
    }
334
335
    /**
336
     * Split the sequence in a sequence of 2 sequences splitted at the given position
337
     *
338
     * @throws OutOfBoundException
339
     *
340
     * @return Stream<self>
341
     */
342 2
    public function splitAt(int $index): Stream
343
    {
344 2
        return (new Stream(self::class))
345 2
            ->add($this->slice(0, $index))
346 2
            ->add($this->slice($index, $this->size()));
347
    }
348
349
    /**
350
     * Return a sequence with the n first elements
351
     */
352 5
    public function take(int $size): self
353
    {
354 5
        return $this->slice(0, $size);
355
    }
356
357
    /**
358
     * Return a sequence with the n last elements
359
     */
360 2
    public function takeEnd(int $size): self
361
    {
362 2
        return $this->slice($this->size() - $size, $this->size());
363
    }
364
365
    /**
366
     * Append the given sequence to the current one
367
     */
368 7
    public function append(self $seq): self
369
    {
370 7
        $self = new self;
371 7
        $self->values = \array_merge($this->values, $seq->toArray());
372
373 7
        return $self;
374
    }
375
376
    /**
377
     * Return a sequence with all elements from the current one that exist
378
     * in the given one
379
     */
380 13
    public function intersect(self $seq): self
381
    {
382
        return $this->filter(static function($value) use ($seq): bool {
383 13
            return $seq->contains($value);
384 13
        });
385
    }
386
387
    /**
388
     * Concatenate all elements with the given separator
389
     */
390 11
    public function join(string $separator): Str
391
    {
392 11
        return new Str(\implode($separator, $this->values));
393
    }
394
395
    /**
396
     * Add the given element at the end of the sequence
397
     *
398
     * @param mixed $element
399
     */
400 115
    public function add($element): self
401
    {
402 115
        $self = clone $this;
403 115
        $self->values[] = $element;
404 115
        $self->size = $this->size() + 1;
405
406 115
        return $self;
407
    }
408
409
    /**
410
     * Sort the sequence in a different order
411
     *
412
     * @param callable(mixed, mixed): int $function
413
     */
414 3
    public function sort(callable $function): self
415
    {
416 3
        $self = clone $this;
417 3
        \usort($self->values, $function);
418
419 3
        return $self;
420
    }
421
422
    /**
423
     * Reduce the sequence to a single value
424
     *
425
     * @param mixed $carry
426
     * @param callable(mixed, mixed) $reducer
427
     *
428
     * @return mixed
429
     */
430 42
    public function reduce($carry, callable $reducer)
431
    {
432 42
        return \array_reduce($this->values, $reducer, $carry);
433
    }
434
435
    /**
436
     * Return the same sequence but in reverse order
437
     *
438
     * @return self
439
     */
440 3
    public function reverse(): self
441
    {
442 3
        $self = clone $this;
443 3
        $self->values = \array_reverse($this->values);
444
445 3
        return $self;
446
    }
447
448 4
    public function empty(): bool
449
    {
450 4
        return !$this->has(0);
451
    }
452
}
453