用PHP将由括号分隔的键名字符串转换为多维关联数组

4

我有一个字符串,其中有一些带方括号的变量名,例如:

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

我需要创建一个多维数组,其中包含与字符串中表示的相同键($value只是一个无关紧要的字符串值):
$arr = [ 'key' => [ 'subkey' => [ 'otherkey' => $value ] ] ];

或者如果您喜欢另一种符号表示法:

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

理想情况下,我希望像字符串一样添加数组键,但据我所知这是不可能的。我认为array_push() 在这里不能起到作用。起初我以为我可以使用正则表达式从字符串中获取方括号中的数值:

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

但是我只有一个没有任何层次结构的非关联数组,对我来说没有用。

因此,我想到了以下解决方案:

$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;
}

现在,这个“works”(即使字符串的 "keys" 数量不同)但在我看来它看起来很丑陋和过于复杂。有更好的方法来做到这一点吗?

这听起来在 http://codereview.stackexchange.com/ 上会更好。 - chris85
有没有可能输入像这样的内容:[key1][subkey1][otherkey1] bla bla [key2][subkey2][otherkey2] - HamZa
@chris85,抱歉不知道有codereview,谢谢。 - unfulvio
不是@HamZa,字符串的格式应该如我所写 - 具有可变数量的[key]。我知道,正如derokorian所说,可以避免使用preg_match,而是要将字符串分割。 - unfulvio
2个回答

7

当我看到 preg_* 和如此简单的模式时,我总是担心。如果您对 $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);

哦,是的,实际上我也考虑过这个问题,但为了简洁起见,我使用了 preg_match 版本,那么你认为没有其他方法可以“追加”键到一个数组中吗? - unfulvio
我的意思是你可以将它变成一个字符串来进行评估...但在我看来,eval 是邪恶的,应该避免使用。 - Derokorian

3

我使用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);

输出内容:
Array
(
    [key] => Array
        (
            [subkey] => Array
                (
                    [otherkey] => Array
                        (
                            [subotherkey] => Array
                                (
                                    [foo] => works
                                )

                        )

                )

        )

)

Online demo


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接