Passed
Pull Request — master (#32)
by Stephen
03:20
created

ArrayHelpers::except()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 1
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Sfneal\Helpers\Arrays;
4
5
class ArrayHelpers
6
{
7
    // todo: remove 'array' prefix from method names
8
9
    /**
10
     * @var array
11
     */
12
    private $array;
13
14
    /**
15
     * ArrayHelpers constructor.
16
     *
17
     * @param array $array
18
     */
19
    public function __construct(array $array)
20
    {
21
        $this->array = $array;
22
    }
23
24
    /**
25
     * Returns a chunked array with calculated chunk size.
26
     *
27
     * @param int $min
28
     * @param int|null $max
29
     * @param bool $no_remainders
30
     * @param bool $preserve_keys
31
     * @return array
32
     */
33
    public function chunks(int $min = 0, int $max = null, bool $no_remainders = false, bool $preserve_keys = true): array
34
    {
35
        $chunks = array_chunk(
36
            $this->array,
37
            (new ChunkSizer(count($this->array), $min, $max))->execute(),
38
            $preserve_keys
39
        );
40
41
        // Check if the first chunk is the same length as the last chunk
42
        if ($no_remainders && count($chunks[0]) != count(array_reverse($chunks)[0])) {
43
            $remainder = array_pop($chunks);
44
            $last_chunk = array_pop($chunks);
45
46
            // Add the remainder chunk to the last equal sized chunk
47
            $chunks[] = array_merge($last_chunk, $remainder);
48
        }
49
50
        return $chunks;
51
    }
52
53
    /**
54
     * Flatten a multidimensional array into a 2D array without nested keys.
55
     *
56
     * @param bool $nest_keys
57
     * @return array
58
     */
59
    public function flattenKeys(bool $nest_keys = true): array
60
    {
61
        // todo: possible use while loop for multi level nesting?
62
        $flat = [];
63
        foreach (array_keys($this->array) as $key) {
64
            if (is_array($this->array[$key])) {
65
                // If the key is an array, add each children keys to flattened array
66
                foreach ($this->array[$key] as $k => $v) {
67
                    if ($nest_keys) {
68
                        $flat[$key.'_'.$k] = $v;
69
                    } else {
70
                        $flat[$k] = $v;
71
                    }
72
                }
73
            } else {
74
                $flat[$key] = $this->array[$key];
75
            }
76
        }
77
78
        return $flat;
79
    }
80
81
    /**
82
     * Remove particular keys from a multidimensional array.
83
     *
84
     * @param array|string $keys
85
     * @return array
86
     */
87
    public function removeKeys($keys): array
88
    {
89
        $all_keys = array_keys($this->array);
90
        foreach ((array) $keys as $key) {
91
            if (in_array($key, $all_keys)) {
92
                unset($this->array[$key]);
93
            }
94
        }
95
96
        return $this->array;
97
    }
98
99
    /**
100
     * Sum the values of two arrays.
101
     *
102
     * @param array $array2
103
     * @return array
104
     */
105
    public function sum(array $array2): array
106
    {
107
        // todo: add ability to pass array of arrays
108
        $array = [];
109
        foreach ($this->array as $index => $value) {
110
            $array[$index] = isset($array2[$index]) ? $array2[$index] + $value : $value;
111
        }
112
113
        return $array;
114
    }
115
116
    /**
117
     * Determine if all values in an array of key => value pairs are unique.
118
     *
119
     * @return bool
120
     */
121
    public function valuesUnique(): bool
122
    {
123
        try {
124
            // Count the number of unique array values
125
            // Check to see if there is more than unique array_value
126
            return count(array_unique(array_values($this->array))) >= count(array_values($this->array));
127
        }
128
129
        // Handle nested arrays by comparing number unique keys
130
        catch (\ErrorException $exception) {
131
            $values = [];
132
            $valueCount = 0;
133
            foreach (array_values($this->array) as $value) {
134
                $values = array_merge($values, $value);
135
                $valueCount += count($value);
136
            }
137
138
            return count($values) == $valueCount;
139
        }
140
    }
141
142
    /**
143
     * Determine if all array_values are equal to a certain value.
144
     *
145
     * @param mixed $value
146
     * @return bool
147
     */
148
    public function valuesEqual($value): bool
149
    {
150
        // Check if all array values are equal to a certain value
151
        return count(array_keys($this->array, $value)) == count($this->array);
152
    }
153
154
    /**
155
     * Determine if all array_values are NOT equal to a certain value.
156
     *
157
     * @param mixed $value
158
     * @return bool
159
     */
160
    public function valuesNotEqual($value): bool
161
    {
162
        return ! $this->valuesEqual($value);
163
    }
164
165
    /**
166
     * Determine if an array is multidimensional and has keys.
167
     *
168
     * @return bool
169
     */
170
    public function hasKeys(): bool
171
    {
172
        // Array doesn't have keys if the array is the same as the array values
173
        if ($this->array == array_values($this->array)) {
174
            return false;
175
        }
176
177
        return count($this->array) == count($this->array, COUNT_RECURSIVE);
178
    }
179
180
    /**
181
     * Remove specific arrays of keys without modifying the original array.
182
     *
183
     * @param array $except
184
     * @return array
185
     */
186
    public function except(array $except): array
187
    {
188
        return array_diff_key($this->array, array_flip((array) $except));
189
    }
190
191
    /**
192
     * Remove a key from an array & return the key's value.
193
     *
194
     * @param string $key
195
     * @return mixed
196
     */
197
    public function pop(string $key)
198
    {
199
        // Get the value
200
        $value = $this->array[$key];
201
202
        // Remove the value from the array
203
        unset($this->array[$key]);
204
205
        // Return the value
206
        return $value;
207
    }
208
209
    /**
210
     * Remove a key from an array & the new array without the key.
211
     *
212
     * @param array|string $keys
213
     * @return array
214
     */
215
    public function unset($keys): array
216
    {
217
        // Remove the values from the array
218
        foreach ((array) $keys as $key) {
219
            unset($this->array[$key]);
220
        }
221
222
        // Return the new array
223
        return $this->array;
224
    }
225
226
    /**
227
     * Determine if all values in an array are null.
228
     *
229
     * @return bool
230
     */
231
    public function valuesNull(): bool
232
    {
233
        return $this->valuesEqual(null);
234
    }
235
236
    /**
237
     * Retrieve a random array of elements.
238
     *
239
     * @param int $items
240
     * @return array
241
     */
242
    public function random(int $items): array
243
    {
244
        // Get a random array of keys
245
        $keys = array_rand($this->array, $items);
246
247
        // Return array with only the randomly selected keys
248
        return array_filter(
249
            $this->array,
250
            function ($value, $key) use ($keys) {
251
                return in_array($key, $keys);
0 ignored issues
show
Bug introduced by
It seems like $keys can also be of type integer and string; however, parameter $haystack of in_array() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

251
                return in_array($key, /** @scrutinizer ignore-type */ $keys);
Loading history...
252
            },
253
            ARRAY_FILTER_USE_BOTH
254
        );
255
    }
256
257
    /**
258
     * Return a flat array of values that were found in the $first array that are not found in the $second.
259
     *
260
     * @param array $array
261
     * @param bool $toArray
262
     * @return \Illuminate\Support\Collection|array
263
     */
264
    public function diffFlat(array $array, bool $toArray = true)
265
    {
266
        $collection = collect($this->array)
267
            ->diff($array)
268
            ->flatten();
269
270
        // Return as array
271
        if ($toArray) {
272
            return $collection->toArray();
273
        }
274
275
        // Return as Collection
276
        return $collection;
277
    }
278
}
279