2011-11-17 180 views
1

我在PHP中,并且有一个看起来像这样的数组。单个维数组,其键是括号字符串。将非嵌套和括号数组转换为嵌套数组

array(
    'matrix[min_rows]' => '0', 
    'matrix[max_rows]' => '', 
    'matrix[col_order][]' => 'col_new_1', 
    'matrix[cols][col_new_0][type]' => 'text', 
    'matrix[cols][col_new_1][type]' => 'text', 
    'matrix[cols][col_new_0][label]' => 'Cell 1', 
    'matrix[cols][col_new_1][label]' => 'Cell 2', 
    'matrix[cols][col_new_0][name]' => 'cell_1', 
    'matrix[cols][col_new_1][name]' => 'cell_2', 
    'matrix[cols][col_new_0][instructions]' => '', 
    'matrix[cols][col_new_1][instructions]' => '', 
    'matrix[cols][col_new_0][width]' => '33%', 
    'matrix[cols][col_new_1][width]' => '', 
    'matrix[cols][col_new_0][settings][maxl]' => '', 
    'matrix[cols][col_new_0][settings][fmt]' => 'none', 
    'matrix[cols][col_new_0][settings][content]' => 'all', 
    'matrix[cols][col_new_1][settings][maxl]' => '140', 
    'matrix[cols][col_new_1][settings][multiline]' => 'y', 
    'matrix[cols][col_new_1][settings][fmt]' => 'none', 
    'matrix[cols][col_new_1][settings][content]' => 'all', 
) 

是否有将其转换成一个正常的嵌套数组没有简单的方法,即:

array(
    'matrix' => array(
     'min_rows' => '0', 
     'max_rows' => '', 
     'col_order' => array('col_new_1'), 
     'cols' => array(
      'col_new_0' => array(
       'type' => 'text', 
       'label' => 'Cell 1', 
....etc.... 

这是我目前的解决方案,但我在想,如果有更多的东西本地或高效:

foreach ($decoded_field_type_settings as $key => $value) 
{ 
    if (preg_match_all('/\[(.*?)\]/', $key, $matches)) 
    { 
     $new_key = substr($key, 0, strpos($key, '[')); 

     if (! isset($field_type_settings[$new_key])) 
     { 
      $field_type_settings[$new_key] = array(); 
     } 

     $array =& $field_type_settings[$new_key]; 

     $count = count($matches[1]) - 1; 

     foreach ($matches[1] as $i => $sub_key) 
     { 
      if (! $sub_key) 
      { 
       if ($i < $count) 
       { 
        $array[] = array(); 
       } 
       else 
       { 
        $array[] = $value; 
       } 
      } 
      else 
      { 
       if (! isset($array[$sub_key])) 
       { 
        if ($i < $count) 
        { 
         $array[$sub_key] = array(); 
        } 
        else 
        { 
         $array[$sub_key] = $value; 
        } 
       } 
      } 

      if ($i < $count) 
      { 
       $array =& $array[$sub_key]; 
      } 
     } 
    } 
    else 
    { 
     $field_type_settings[$key] = $value; 
    } 
} 

更新:我在下面发布了一个答案。

+1

什么是原始数据的来源是什么? – 2011-11-17 21:50:09

+0

这是一个由jQuery.serializeArray()填充的隐藏表单字段。我捎带第三方应用程序,所以我无法更改此数据。 – Rob

+0

我刚刚发布了一个使用'http_build_query()'和'parse_str()'的答案,但是重新阅读了你的问题,发现你已经有了这个答案。问题是,您没有将解决方案作为答案发布。请编辑您的问题以删除解决方案,将解决方案作为答案发布,并将其标为绿色勾号(这样您的问题就被视为已解决)。哦,你已经6年没有在现场了。 – mickmackusa

回答

0

这是最简单的解决方案,不涉及正则表达式解析:

$original_array = array(
    'matrix[min_rows]' => '0', 
    'matrix[max_rows]' => '', 
    'matrix[col_order][]' => 'col_new_1', 
    'matrix[cols][col_new_0][type]' => 'text', 
    'matrix[cols][col_new_1][type]' => 'text', 
    'matrix[cols][col_new_0][label]' => 'Cell 1', 
    'matrix[cols][col_new_1][label]' => 'Cell 2', 
    'matrix[cols][col_new_0][name]' => 'cell_1', 
    'matrix[cols][col_new_1][name]' => 'cell_2', 
    'matrix[cols][col_new_0][instructions]' => '', 
    'matrix[cols][col_new_1][instructions]' => '', 
    'matrix[cols][col_new_0][width]' => '33%', 
    'matrix[cols][col_new_1][width]' => '', 
    'matrix[cols][col_new_0][settings][maxl]' => '', 
    'matrix[cols][col_new_0][settings][fmt]' => 'none', 
    'matrix[cols][col_new_0][settings][content]' => 'all', 
    'matrix[cols][col_new_1][settings][maxl]' => '140', 
    'matrix[cols][col_new_1][settings][multiline]' => 'y', 
    'matrix[cols][col_new_1][settings][fmt]' => 'none', 
    'matrix[cols][col_new_1][settings][content]' => 'all', 
); 

$query_string = http_build_query($original_array); 

$final_array = array(); 

parse_str($query_string, $final_array); 

var_dump($final_array); 
1

这可能会实现,但它可能会产生一些警告:

$matrix = array(); 
foreach($arr as $key => $value) { 
    eval('$' . $key . ' = \'' . $value . '\';'); 
} 

var_dump($matrix); 
+0

我正要提出这个想法。除了做一个大型的标记工作,这是我能想到的唯一有效的想法..丑陋的,但工程... –

+0

评估键的代码?玩的开心! – hakre

+0

我也想过eval,虽然我通常听说你应该避免出于安全目的,等等......这里有什么要考虑的吗? (也许你至少可以确保字符串没有分号或$符号或什么...?) – joshuahedlund

0

看来,OP想,作为输出,一个数组声明可直接通过PHP解析。所以我建议使用var_export()

$array = array(
    'matrix[min_rows]' => '0', 
    // ...... 
    // ...... 
    // ...... 
    'matrix[cols][col_new_1][settings][content]' => 'all' 
); 

$matrix = array(); 

foreach ($array as $key => $value) 
{ 
    // fix missing quotes around array indexes 
    $key = str_replace(array("[", "]", "['']"), array("['", "']", "[]"), $key); 
    // fill PHP array 
    eval('$'.$key.' = $value;'); 
} 

var_export($matrix); 
0

我想这应该这样做...

<?php 
function convert2dTo3d($source) { 
    $refs = array(); 
    $output = array(); 

    foreach ($source AS $key => $val) { 
     $tok = strtok($key, '[]'); 

     $prev_tok = NULL; 
     while ($tok !== FALSE) { 
      $this_ref =& $refs[$tok]; 

      if ($prev_tok === NULL) 
       $output[$tok] =& $this_ref; 
      else 
       $refs[$prev_tok][$tok] =& $this_ref; 

      $prev_tok = $tok; 
      $tok = strtok('[]'); 

      if ($tok === FALSE) 
       $refs[$prev_tok] = $val; 
     } 
    } 

    return $output; 
} 


// Test 
$source = array(
    'matrix[min_rows]' => '0', 
    'matrix[max_rows]' => '', 
    'matrix[col_order][]' => 'col_new_1', 
    'matrix[cols][col_new_0][type]' => 'text', 
    'matrix[cols][col_new_1][type]' => 'text', 
    'matrix[cols][col_new_0][label]' => 'Cell 1', 
    'matrix[cols][col_new_1][label]' => 'Cell 2', 
    'matrix[cols][col_new_0][name]' => 'cell_1', 
    'matrix[cols][col_new_1][name]' => 'cell_2', 
    'matrix[cols][col_new_0][instructions]' => '', 
    'matrix[cols][col_new_1][instructions]' => '', 
    'matrix[cols][col_new_0][width]' => '33%', 
    'matrix[cols][col_new_1][width]' => '', 
    'matrix[cols][col_new_0][settings][maxl]' => '', 
    'matrix[cols][col_new_0][settings][fmt]' => 'none', 
    'matrix[cols][col_new_0][settings][content]' => 'all', 
    'matrix[cols][col_new_1][settings][maxl]' => '140', 
    'matrix[cols][col_new_1][settings][multiline]' => 'y', 
    'matrix[cols][col_new_1][settings][fmt]' => 'none', 
    'matrix[cols][col_new_1][settings][content]' => 'all', 
); 

echo "<pre>"; 
print_r(convert2dTo3d($source)); 
echo "</pre>"; 
0

您可以使用一个简单的,基于正则表达式解析器,基于存储的每一个的每串中的信息来创建多维数组关键:

function parse_flat_matrix(array $flat) 
{ 
    $matrix = array(); 
    $varname = 'matrix'; 
    $nameToken = '[a-z0-9_]*'; 

    foreach($flat as $key => $value) 
    { 
     $keys = preg_split(sprintf('/(\[%s\])/', $nameToken), $key, 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); 

     if ($varname !== array_shift($keys)) 
     { 
      throw new InvalidArgumentException(sprintf('Invalid key %s.', $key)); 
     } 

     $p =& $matrix; 
     foreach($keys as $k) 
     { 
      $r = preg_match(sprintf('/^\[(%s)\]$/', $nameToken), $k, $kk); 
      if (!$r) 
      { 
       throw new InvalidArgumentException(sprintf('Invalid subkey %s in key %s.', $k, $key)); 
      } 

      if ('' === $kk[1]) 
      { 
       $p =& $p[]; 
      } 
      else 
      { 
       $p =& $p[$kk[1]]; 
      } 
     } 
     $p = $value; 
     unset($p); 
    } 

    return $matrix; 
} 

有了您的例子给出的数据,它将创建这个数组:

Array 
(
    [min_rows] => 0 
    [max_rows] => 
    [col_order] => Array 
     (
      [0] => col_new_1 
     ) 

    [cols] => Array 
     (
      [col_new_0] => Array 
       (
        [type] => text 
        [label] => Cell 1 
        [name] => cell_1 
        [instructions] => 
        [width] => 33% 
        [settings] => Array 
         (
          [maxl] => 
          [fmt] => none 
          [content] => all 
         ) 

       ) 

      [col_new_1] => Array 
       (
        [type] => text 
        [label] => Cell 2 
        [name] => cell_2 
        [instructions] => 
        [width] => 
        [settings] => Array 
         (
          [maxl] => 140 
          [multiline] => y 
          [fmt] => none 
          [content] => all 
         ) 

       ) 

     ) 

)