Completed
Pull Request — master (#40)
by
unknown
05:34
created

AbstractArray::filter()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 1
ccs 0
cts 0
cp 0
c 0
b 0
f 0
nc 1
1
<?php
2
3
namespace Arrayzy;
4
5
use Arrayzy\Interfaces\ConvertibleInterface;
6
use Arrayzy\Interfaces\DebuggableInterface;
7
use Arrayzy\Interfaces\DoubleEndedQueueInterface;
8
use Arrayzy\Interfaces\SortableInterface;
9
use Arrayzy\Interfaces\TraversableInterface;
10
use Arrayzy\Traits\ConvertibleTrait;
11
use Arrayzy\Traits\DebuggableTrait;
12
use Arrayzy\Traits\DoubleEndedQueueTrait;
13
use Arrayzy\Traits\SortableTrait;
14
use Arrayzy\Traits\TraversableTrait;
15
use ArrayAccess;
16
use ArrayIterator;
17
use Countable;
18
use IteratorAggregate;
19
use Traversable;
20
use Exception;
21
22
/**
23
 * Defines common methods and method signatures.
24
 *
25
 * @author Victor Bocharsky <[email protected]>
26
 */
27
abstract class AbstractArray implements
28
    ArrayAccess,
29
    ConvertibleInterface,
30
    Countable,
31
    DebuggableInterface,
32
    DoubleEndedQueueInterface,
33
    IteratorAggregate,
34
    SortableInterface,
35
    TraversableInterface
36
{
37
    use ConvertibleTrait;
38
39
    use DebuggableTrait;
40
41
    use DoubleEndedQueueTrait;
42
43
    use SortableTrait;
44
45
    use TraversableTrait;
46
47
    /**
48
     * @const string
49
     */
50
    const DEFAULT_SEPARATOR = ', ';
51
52
    /**
53
     * @var array
54
     */
55
    protected $elements = [];
56
57
    /**
58
     * Construct new instance
59
     *
60
     * @param array $elements
61
     */
62 311
    public function __construct(array $elements = [])
63
    {
64 311
        $this->elements = $elements;
65 311
    }
66
67
    // The abstract public method list order by ASC
68
69
    /**
70
     * Create a chunked version of current array.
71
     *
72
     * @param int $size Size of each chunk
73
     * @param bool $preserveKeys Whether array keys are preserved or no
74
     *
75
     * @return AbstractArray An array of chunks from the current array
76
     */
77
    abstract public function chunk($size, $preserveKeys = false);
78
79
    /**
80
     * Clear the current array.
81
     *
82
     * @return AbstractArray The current empty array
83
     */
84
    abstract public function clear();
85
86
    /**
87
     * Create an array using the current array as keys and the other array as values.
88
     *
89
     * @param array $array Values array
90
     *
91
     * @return AbstractArray An array with values from the other array
92
     */
93
    abstract public function combine(array $array);
94
95
    /**
96
     * Compute the current array values which not present in the given one.
97
     *
98
     * @param array $array Array for diff
99
     *
100
     * @return AbstractArray An array containing all the entries from this array
101
     * that are not present in $array
102
     */
103
    abstract public function diff(array $array);
104
105
    /**
106
     * Filter the current array for elements satisfying the predicate $func.
107
     *
108
     * @param callable $func
109
     *
110
     * @return AbstractArray An array with only element satisfying $func
111
     */
112
    abstract public function filter(callable $func);
113
114
    /**
115
     * Exchanges all keys of current array with their associated values.
116
     *
117
     * @return AbstractArray An array with flipped elements
118
     */
119
    abstract public function flip();
120
121
    /**
122
     * Compute the current array values which present in the given one.
123
     *
124
     * @param array $array Array for intersect
125
     *
126
     * @return AbstractArray An array with containing all the entries from this array
127
     * that are present in $array
128
     */
129
    abstract public function intersect(array $array);
130
131
    /**
132
     * Compute the current array values with additional index check which present in the given one.
133
     *
134
     * @param array $array Array for intersect
135
     *
136
     * @return AbstractArray An array with containing all the entries from this array
137
     * that are present in $array. Note that the keys are also used in the comparison
138
     * unlike in intersect().
139
     */
140
    abstract public function intersectAssoc(array $array);
141
142
    /**
143
     * Compute the current array using keys for comparison which present in the given one.
144
     *
145
     * @param array $array Array for intersect
146
     *
147
     * @return AbstractArray An array with containing all the entries from this array
148
     * which have keys that are present in $array.
149
     */
150
     abstract public function intersectKey(array $array);
151
152
    /**
153
     * Apply the given function to the every element of the current array,
154
     * collecting the results.
155
     *
156
     * @param callable $func
157
     *
158
     * @return AbstractArray An array with modified elements
159
     */
160
    abstract public function map(callable $func);
161
162
    /**
163
     * Merge the current array with the provided one. The latter array is overwriting.
164
     *
165
     * @param array $array Array to merge with (overwrites)
166
     * @param bool $recursively Whether array will be merged recursively or no
167
     *
168
     * @return AbstractArray An array with the keys/values from $array added
169
     */
170
    abstract public function merge(array $array, $recursively = false);
171
172
    /**
173
     * Pad the current array to the specified size with a given value.
174
     *
175
     * @param int $size Size of the result array
176
     * @param mixed $value Empty value by default
177
     *
178
     * @return AbstractArray An array padded to $size with $value
179
     */
180
    abstract public function pad($size, $value);
181
182
    /**
183
     * Create a numerically re-indexed array based on the current array.
184
     *
185
     * @return AbstractArray An array with re-indexed elements
186
     */
187
    abstract public function reindex();
188
189
    /**
190
     * Replace values in the current array with values in the given one
191
     * that have the same key.
192
     *
193
     * @param array $array Array of replacing values
194
     * @param bool $recursively Whether array will be replaced recursively or no
195
     *
196
     * @return AbstractArray An array with the same keys but new values
197
     */
198
    abstract public function replace(array $array, $recursively = false);
199
200
    /**
201
     * Reverse the values order of the current array.
202
     *
203
     * @param bool $preserveKeys Whether array keys are preserved or no
204
     *
205
     * @return AbstractArray An array with the order of the elements reversed
206
     */
207
    abstract public function reverse($preserveKeys = false);
208
209
    /**
210
     * Randomize elements order of the current array.
211
     *
212
     * @return AbstractArray An array with the shuffled elements order
213
     */
214
    abstract public function shuffle();
215
216
    /**
217
     * Extract a slice of the current array.
218
     *
219
     * @param int $offset Slice begin index
220
     * @param int|null $length Length of the slice
221
     * @param bool $preserveKeys Whether array keys are preserved or no
222
     *
223
     * @return AbstractArray A new array, which is slice of the current array
224
     * with specified $length
225
     */
226
    abstract public function slice($offset, $length = null, $preserveKeys = false);
227
228
    /**
229
     * Remove duplicate values from the current array.
230
     *
231
     * @param int|null $sortFlags
232
     *
233
     * @return AbstractArray An array with only unique elements
234
     */
235
    abstract public function unique($sortFlags = null);
236
237
    /**
238
     * Apply the given function to the every element of the current array,
239
     * discarding the results.
240
     *
241
     * @param callable $func
242
     * @param bool $recursively Whether array will be walked recursively or no
243
     *
244
     * @return AbstractArray An array with modified elements
245
     */
246
    abstract public function walk(callable $func, $recursively = false);
247
248
    // The public static method list order by ASC
249
250
    /**
251
     * Create a new instance.
252
     *
253
     * @param array $elements
254
     *
255
     * @return AbstractArray Returns created instance
256
     */
257 19
    public static function create(array $elements = [])
258
    {
259 19
        return new static($elements);
260
    }
261
262
    /**
263
     * Decode a JSON string to new instance.
264
     *
265
     * @param string $json The JSON string being decoded
266
     * @param int $options Bitmask of JSON decode options
267
     * @param int $depth Specified recursion depth
268
     *
269
     * @return AbstractArray The created array
270
     */
271 8
    public static function createFromJson($json, $options = 0, $depth = 512)
272
    {
273 8
        return new static(json_decode($json, true, $depth, $options));
274
    }
275
276
    /**
277
     * Create a new instance filled with values from an object implementing ArrayAccess.
278
     *
279
     * @param ArrayAccess $elements Object that implements ArrayAccess
280
     *
281
     * @return AbstractArray Returns created instance
282
     */
283 8
    public static function createFromObject(ArrayAccess $elements)
284
    {
285 8
        $array = new static();
286
287 8
        foreach ($elements as $key => $value) {
288 6
            $array[$key] = $value;
289 8
        }
290
291 8
        return $array;
292
    }
293
294
    /**
295
     * Explode a string to new instance by specified separator.
296
     *
297
     * @param string $string Converted string
298
     * @param string $separator Element's separator
299
     *
300
     * @return AbstractArray The created array
301
     */
302 6
    public static function createFromString($string, $separator)
303
    {
304 6
        return new static(explode($separator, $string));
305
    }
306
307
    /**
308
     * Create a new instance containing a range of elements.
309
     *
310
     * @param mixed $low First value of the sequence
311
     * @param mixed $high The sequence is ended upon reaching the end value
312
     * @param int $step Used as the increment between elements in the sequence
313
     *
314
     * @return AbstractArray The created array
315
     */
316 1
    public static function createWithRange($low, $high, $step = 1)
317
    {
318 1
        return new static(range($low, $high, $step));
319
    }
320
321
    // The public method list order by ASC
322
323
    /**
324
     * Check if the given value exists in the array.
325
     *
326
     * @param mixed $element Value to search for
327
     *
328
     * @return bool Returns true if the given value exists in the array, false otherwise
329
     */
330 4
    public function contains($element)
331
    {
332 4
        return in_array($element, $this->elements, true);
333
    }
334
335
    /**
336
     * Check if the given key/index exists in the array.
337
     *
338
     * @param mixed $key Key/index to search for
339
     *
340
     * @return bool Returns true if the given key/index exists in the array, false otherwise
341
     */
342 4
    public function containsKey($key)
343
    {
344 4
        return array_key_exists($key, $this->elements);
345
    }
346
347
    /**
348
     * Returns the number of values in the array.
349
     *
350
     * @link http://php.net/manual/en/function.count.php
351
     *
352
     * @return int total number of values
353
     */
354 31
    public function count()
355
    {
356 31
        return count($this->elements);
357
    }
358
359
    /**
360
     * Clone current instance to new instance.
361
     *
362
     * @deprecated Should be removed
363
     *
364
     * @return AbstractArray Shallow copy of $this
365
     */
366
    public function createClone()
367
    {
368
        return clone $this;
369
    }
370
371
    /**
372
     * Return slice of an array except given keys.
373
     * 
374
     * @param array $keys List of keys to exclude
375
     * 
376
     * @return AbstractArray The created array
377
     */
378 3
    public function except(array $keys)
379
    {
380 3
        return new static(array_diff_key($this->elements, array_flip($keys)));
381
    }
382
383
    /**
384
     * Find the given value in An array using a closure
385
     *
386
     * @param callable $func
387
     *
388
     * @return bool Returns true if the given value is found, false otherwise
389
     */
390 4
    public function exists(callable $func)
391
    {
392 4
        $isExists = false;
393
394 4
        foreach ($this->elements as $key => $value) {
395 3
            if ($func($key, $value)) {
396 1
                $isExists = true;
397 1
                break;
398
            }
399 4
        }
400
401 4
        return $isExists;
402
    }
403
404
    /**
405
     * Returns the first occurrence of a value that satisfies the predicate $func.
406
     *
407
     * @param callable $func
408
     *
409
     * @return mixed The first occurrence found
410
     */
411 1
    public function find(callable $func)
412
    {
413 1
        $found = null;
414
415 1
        foreach ($this->elements as $key => $value) {
416 1
            if($func($value, $key)) {
417 1
                $found = $value;
418 1
                break;
419
            }
420 1
        }
421
422 1
        return $found;
423
    }
424
425
    /**
426
     * Create an iterator over this array.
427
     *
428
     * @link http://php.net/manual/en/iteratoraggregate.getiterator.php
429
     *
430
     * @return Traversable An instance of an object implementing <b>Iterator</b>
431
     */
432 12
    public function getIterator()
433
    {
434 12
        return new ArrayIterator($this->elements);
435
    }
436
437
    /**
438
     * Return an array all the keys of this array.
439
     *
440
     * @return array An array of all keys
441
     */
442 10
    public function getKeys()
443
    {
444 10
        return array_keys($this->elements);
445
    }
446
447
    /**
448
     * Pick a random value out of this array.
449
     *
450
     * @return mixed Random value of array
451
     *
452
     * @throws \RangeException If array is empty
453
     */
454 3
    public function getRandom()
455
    {
456 3
        return $this->offsetGet($this->getRandomKey());
457
    }
458
459
    /**
460
     * Pick a random key/index from the keys of this array.
461
     *
462
     * @return mixed Random key/index of array
463
     *
464
     * @throws \RangeException If array is empty
465
     */
466 6
    public function getRandomKey()
467
    {
468 6
        return $this->getRandomKeys(1);
469
    }
470
471
    /**
472
     * Pick a given number of random keys/indexes out of this array.
473
     *
474
     * @param int $number The number of keys/indexes (should be <= $this->count())
475
     *
476
     * @return mixed Random keys or key of array
477
     *
478
     * @throws \RangeException
479
     */
480 27
    public function getRandomKeys($number)
481
    {
482 27
        $number = (int) $number;
483
484 27
        $count = $this->count();
485 27
        if ($number === 0 || $number > $count) {
486 3
            throw new \RangeException(sprintf(
487 3
                'Number of requested keys (%s) must be equal or lower than number of elements in this array (%s)',
488 3
                $number,
489
                $count
490 3
            ));
491
        }
492
493 24
        return array_rand($this->elements, $number);
494
    }
495
496
    /**
497
     * Pick a given number of random values with non-duplicate indexes out of the array.
498
     *
499
     * @param int $number The number of values (should be > 1 and < $this->count())
500
     *
501
     * @return array Random values of array
502
     *
503
     * @throws \RangeException
504
     */
505 6
    public function getRandomValues($number)
506
    {
507 6
        $values = [];
508
509 6
        $keys = $number > 1 ? $this->getRandomKeys($number) : [$this->getRandomKeys($number)];
510 6
        foreach ($keys as $key) {
511 6
            $values[] = $this->offsetGet($key);
512 6
        }
513
514 6
        return $values;
515
    }
516
517
    /**
518
     * Return an array of all values from this array numerically indexed.
519
     *
520
     * @return mixed An array of all values
521
     */
522 4
    public function getValues()
523
    {
524 4
        return array_values($this->elements);
525
    }
526
527
    /**
528
     * Alias of search() method. Search for a given element and return
529
     * the index of its first occurrence.
530
     *
531
     * @param mixed $element Value to search for
532
     *
533
     * @return mixed The corresponding key/index
534
     */
535 4
    public function indexOf($element)
536
    {
537 4
        return $this->search($element);
538
    }
539
540
    /**
541
     * Check whether array is associative or not.
542
     *
543
     * @return bool Returns true if associative, false otherwise
544
     */
545 4
    public function isAssoc()
546
    {
547 4
        $isAssoc = false;
548
549 4
        if (!$this->isEmpty()) {
550 3
            $isAssoc = $this->checkType('string');
551 3
        }
552
553 4
        return $isAssoc;
554
    }
555
556
    /**
557
     * Check whether the array is empty or not.
558
     *
559
     * @return bool Returns true if empty, false otherwise
560
     */
561 12
    public function isEmpty()
562
    {
563 12
        return !$this->elements;
564
    }
565
566
    /**
567
     * Check if an array keys are in a given variable type.
568
     *
569
     * @param string $type
570
     *
571
     * @return bool
572
     */
573 6
    private function checkType($type)
574
    {
575 6
        $isInType = true;
576
577 6
        foreach ($this->getKeys() as $key) {
578 6
            if (gettype($key) !== $type) {
579 4
                $isInType = false;
580 4
                break;
581
            }
582 6
        }
583
584 6
        return $isInType;
585
    }
586
587
    /**
588
     * Check whether array is numeric or not.
589
     *
590
     * @return bool Returns true if numeric, false otherwise
591
     */
592 4
    public function isNumeric()
593
    {
594 4
        $isNumeric = false;
595
596 4
        if (!$this->isEmpty()) {
597 3
            $isNumeric = $this->checkType('integer');
598 3
        }
599
600 4
        return $isNumeric;
601
    }
602
603
    /**
604
     * Whether an offset exists.
605
     *
606
     * @param mixed $offset An offset to check for.
607
     * @link http://php.net/manual/en/arrayaccess.offsetexists.php
608
     *
609
     * @return boolean true on success or false on failure.
610
     */
611 8
    public function offsetExists($offset)
612
    {
613 8
        return isset($this->elements[$offset]);
614
    }
615
616
    /**
617
     * Retrieve the current offset or null.
618
     *
619
     * @param mixed $offset The offset to retrieve.
620
     * @link http://php.net/manual/en/arrayaccess.offsetget.php
621
     *
622
     * @return mixed Can return all value types.
623
     */
624 13
    public function offsetGet($offset)
625
    {
626 13
        return isset($this->elements[$offset])
627 13
            ? $this->elements[$offset]
628 13
            : $this->getDefaultValue()
629 13
        ;
630
    }
631
632
    /**
633
     * Set an offset for this array.
634
     *
635
     * @param mixed $offset The offset to assign the value to.
636
     * @param mixed $value The value to set.
637
     * @link http://php.net/manual/en/arrayaccess.offsetset.php
638
     *
639
     * @return $this
640
     */
641 14
    public function offsetSet($offset, $value)
642
    {
643 14
        if (isset($offset)) {
644 10
            $this->elements[$offset] = $value;
645 10
        } else {
646 4
            $this->elements[] = $value;
647
        }
648
649 14
        return $this;
650
    }
651
652
    /**
653
     * Remove a present offset.
654
     *
655
     * @param mixed $offset The offset to unset.
656
     * @link http://php.net/manual/en/arrayaccess.offsetunset.php
657
     *
658
     * @return $this
659
     */
660 10
    public function offsetUnset($offset)
661
    {
662 10
        unset($this->elements[$offset]);
663
664 10
        return $this;
665
    }
666
667
    /**
668
     * Return slice of an array with just a given keys.
669
     *
670
     * @param array $keys List of keys to return
671
     *
672
     * @return AbstractArray The created array
673
     */
674 3
    public function only(array $keys)
675
    {
676 3
        return new static(array_intersect_key($this->elements, array_flip($keys)));
677
    }
678
679
    /**
680
     * Reduce the array to a single value iteratively combining all values using $func.
681
     *
682
     * @param callable $func callback ($carry, $item) -> next $carry
683
     * @param mixed|null $initial starting value of the $carry
684
     *
685
     * @return mixed Final value of $carry
686
     */
687 1
    public function reduce(callable $func, $initial = null)
688
    {
689 1
        return array_reduce($this->elements, $func, $initial);
690
    }
691
692
    /**
693
     * Search for a given element and return the index of its first occurrence.
694
     *
695
     * @param mixed $element Value to search for
696
     *
697
     * @return mixed The corresponding key/index
698
     */
699 4
    public function search($element)
700
    {
701 4
        return array_search($element, $this->elements, true);
702
    }
703
704
}
705