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?

+3


source to share


2 answers


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);

      

+5


source


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
                                )

                        )

                )

        )

)

      

-

+2


source







All Articles