Completed
Push — master ( 6cf2a9...95445f )
by Bocharsky
8s
created

AbstractArray::search()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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