PHP make a multidimensional associative array from key names in a string separated by brackets

拟墨画扇 提交于 2020-02-01 05:27:07

问题


I have a string with a variable number of key names in brackets, example:

$str = '[key][subkey][otherkey]';

I need to make a multidimensional array that has the same keys represented in the string ($value is just a string value of no importance here):

$arr = [ 'key' => [ 'subkey' => [ 'otherkey' => $value ] ] ];

Or if you prefer this other notation:

$arr['key']['subkey']['otherkey'] = $value;

So ideally I would like to append array keys as I would do with strings, but that is not possible as far as I know. I don't think array_push() can help here. At first I thought I could use a regex to grab the values in square brackets from my string:

preg_match_all( '/\[([^\]]*)\]/', $str, $has_keys, PREG_PATTERN_ORDER );

But I would just have a non associative array without any hierarchy, that is no use to me.

So I came up with something along these lines:

$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 "works" (also if the string has a different number of 'keys') but to me it looks ugly and overcomplicated. Is there a better way to do this?


回答1:


I always worry when I see preg_* and such a simple pattern to work with. I would probably go with something like this if you're confident in the format of $str

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



回答2:


I've come 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);

The output:

Array
(
    [key] => Array
        (
            [subkey] => Array
                (
                    [otherkey] => Array
                        (
                            [subotherkey] => Array
                                (
                                    [foo] => works
                                )

                        )

                )

        )

)

Online demo



来源:https://stackoverflow.com/questions/31103719/php-make-a-multidimensional-associative-array-from-key-names-in-a-string-separat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!