问题
I'm in PHP and I've got an array that looks like this. A single dimension array whose keys are bracketed strings.
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',
)
Is there any easy way to convert that to a normal nested array, ie:
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....
This is my current solution, but I was wondering if there's something more native or efficient:
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;
    }
}
UPDATE: I posted an answer below.
回答1:
This might work, although it would probably generate some warnings:
$matrix = array();
foreach($arr as $key => $value) {
   eval('$' . $key . ' = \'' . $value . '\';');
}
var_dump($matrix);
回答2:
I think this should do it...
<?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>";
回答3:
It seems that the OP wants, as output, an array declaration which can be parsed directly by PHP. So I suggest to use 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);
回答4:
You can make use of a simple, regular expression based parser that creates a multidimensional array based on the information stored in the string per each key:
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;
}
With your example data given, it will create this array:
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
                        )
                )
        )
)
回答5:
This was the simplest solution, involving no regex parsing:
$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);
来源:https://stackoverflow.com/questions/8174787/convert-non-nested-and-bracketed-array-to-nested-array