|
8 | 8 | class Flatten |
9 | 9 | { |
10 | 10 | /** |
11 | | - * Flattens a variable, possible traversable, into a one-dimensional array, recursively. |
12 | | - * |
13 | | - * Each key in the returned one-dimensional array is the join of all keys leading to each value, in all dimensions, |
14 | | - * separated by a given separator. That is a fully-qualified key. |
| 11 | + * Turn off flattening values with integer keys. |
| 12 | + */ |
| 13 | + const FLAG_NUMERIC_NOT_FLATTENED = 0b1; |
| 14 | + |
| 15 | + /** |
| 16 | + * Flattens a variable, possibly traversable, into a one-dimensional array, recursively. |
15 | 17 | * |
16 | | - * Non-traversable values will be returned as-is, after being put into the final array with the fully-qualified key. |
| 18 | + * Each key (fully-qualified key or FQK) in the returned one-dimensional array is the join of all keys leading to |
| 19 | + * each (non-traversable) value, in all dimensions, separated by a given separator. |
17 | 20 | * |
18 | | - * An initial prefix can be optionally provided, but it will not separated using the separator. |
| 21 | + * An initial prefix can be optionally provided, but it will not be separated with the specified separator. |
19 | 22 | * |
20 | 23 | * @param mixed $var |
21 | 24 | * @param string $separator |
22 | 25 | * @param string $prefix |
| 26 | + * @param int $flags |
23 | 27 | * @return array One-dimensional array containing all values from all possible traversable dimensions in given input. |
| 28 | + * @see Flatten::FLAG_NUMERIC_NOT_FLATTENED |
24 | 29 | */ |
25 | | - public static function flatten($var, $separator = '.', $prefix = '') |
| 30 | + public static function flatten($var, $separator = '.', $prefix = '', $flags = 0) |
26 | 31 | { |
27 | 32 | $flattened = []; |
28 | | - foreach (self::flattenGenerator($var, $separator, '') as $key => $value) { |
| 33 | + foreach (self::flattenGenerator($var, $separator, '', $flags) as $key => $value) { |
29 | 34 | $flattened[$prefix . $key] = $value; |
30 | 35 | } |
31 | 36 | return $flattened; |
32 | 37 | } |
33 | 38 |
|
34 | | - private static function flattenGenerator($var, $separator, $prefix = '') |
| 39 | + private static function flattenGenerator($var, $separator, $prefix = '', $flags) |
35 | 40 | { |
36 | | - if (self::canTraverse($var)) { |
37 | | - $prefix .= (empty($prefix) ? '' : $separator); |
38 | | - foreach ($var as $key => $value) { |
39 | | - foreach (self::flattenGenerator($value, $separator, $prefix .$key) as $k => $v) { |
40 | | - yield $k => $v; |
41 | | - } |
42 | | - } |
43 | | - } else { |
| 41 | + if (!self::canTraverse($var)) { |
44 | 42 | yield $prefix => $var; |
| 43 | + return; |
| 44 | + } |
| 45 | + |
| 46 | + if ($flags & self::FLAG_NUMERIC_NOT_FLATTENED) { |
| 47 | + list ($values, $var) = self::filterNumericKeysAndGetValues($var); |
| 48 | + yield $prefix => $values; |
| 49 | + } |
| 50 | + |
| 51 | + $prefix .= (empty($prefix) ? '' : $separator); |
| 52 | + foreach ($var as $key => $value) { |
| 53 | + foreach (self::flattenGenerator($value, $separator, $prefix . $key, $flags) as $k => $v) { |
| 54 | + yield $k => $v; |
| 55 | + } |
45 | 56 | } |
46 | 57 | } |
47 | 58 |
|
48 | 59 | private static function canTraverse($var) |
49 | 60 | { |
50 | 61 | return is_array($var) || ($var instanceof \Traversable); |
51 | 62 | } |
| 63 | + |
| 64 | + private static function filterNumericKeysAndGetValues($var) |
| 65 | + { |
| 66 | + $values = []; |
| 67 | + $var = array_filter($var, function($value, $key) use (&$values) { |
| 68 | + if (is_int($key)) { |
| 69 | + $values[$key] = $value; |
| 70 | + return false; |
| 71 | + } |
| 72 | + return true; |
| 73 | + }, ARRAY_FILTER_USE_BOTH); |
| 74 | + return [$values, $var]; |
| 75 | + } |
52 | 76 | } |
0 commit comments