PHP creates multidimensional associative array from key names in a parenthesized string
I have a string with a variable number of key names in parentheses, for example:
$str = '[key][subkey][otherkey]';
I need to create a multidimensional array with the same keys presented in a string ( $value
- it's just a string value, not relevant here):
$arr = [ 'key' => [ 'subkey' => [ 'otherkey' => $value ] ] ];
Or, if you prefer this other notation:
$arr['key']['subkey']['otherkey'] = $value;
Ideally, I would like to add array keys as with strings, but this is not possible as far as I know. I don't think it array_push()
can help here. At first I thought I could use a regex to grab the bracketed values ββfrom my string:
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
But I just would have a non-associative array without some kind of hierarchy, it's useless for me.
So, I came up with something like this:
$str = '[key][subkey][otherkey]';
$value = 'my_value';
$arr = [];
preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );
if ( isset( $has_keys[1] ) ) {
$keys = $has_keys[1];
$k = count( $keys );
if ( $k > 1 ) {
for ( $i=0; $i<$k-1; $i++ ) {
$arr[$keys[$i]] = walk_keys( $keys, $i+1, $value );
}
} else {
$arr[$keys[0]] = $value;
}
$arr = array_slice( $arr, 0, 1 );
}
var_dump($arr);
function walk_keys( $keys, $i, $value ) {
$a = '';
if ( isset( $keys[$i+1] ) ) {
$a[$keys[$i]] = walk_keys( $keys, $i+1, $value );
} else {
$a[$keys[$i]] = $value;
}
return $a;
}
Now this one "works" (also if the string has a different number of "keys"), but it looks ugly and complicated to me. Is there a better way to do this?
source to share
I'm always worried when I see preg_ * and such a simple template to work with. I would probably go with something like this if you are sure of the $ str format
<?php
// initialize variables
$str = '[key][subkey][otherkey]';
$val = 'my value';
$arr = [];
// Get the keys we want to assign
$keys = explode('][', trim($str, '[]'));
// Get a reference to where we start
$curr = &$arr;
// Loops over keys
foreach($keys as $key) {
// get the reference for this key
$curr = &$curr[$key];
}
// Assign the value to our last reference
$curr = $val;
// visualize the output, so we know its right
var_dump($arr);
source to share
I came up with a simple loop using : array_combine()
$in = '[key][subkey][otherkey][subotherkey][foo]';
$value = 'works';
$output = [];
if(preg_match_all('~\[(.*?)\]~s', $in, $m)) { // Check if we got a match
$n_matches = count($m[1]); // Count them
$tmp = $value;
for($i = $n_matches - 1; $i >= 0; $i--) { // Loop through them in reverse order
$tmp = array_combine([$m[1][$i]], [$tmp]); // put $m[1][$i] as key and $tmp as value
}
$output = $tmp;
} else {
echo 'no matches';
}
print_r($output);
Output:
Array
(
[key] => Array
(
[subkey] => Array
(
[otherkey] => Array
(
[subotherkey] => Array
(
[foo] => works
)
)
)
)
)
source to share