转换数组关联递归


Transform array associative recursive

我们有一个具有以下值的数组:

$a = array("a", "a.b", "a.b.c", "X", "X.Y", "X.Y.Z");

目标是将第一个数组修改为以下结构:

$a = array(
     "a" => array(
         "b" => array(
             "c" => array(),
         ),
     ),
     "X" => array(
         "Y" => array(
             "Z" => array(),
         ),
     ),
);

我为什么要问?我的客户有一个商店类别的表格。这些类别在一列中(简化!

 +-----------------------+
 |id |       name        |
 +---|-------------------+
 | 4 | A                 |
 | 5 | A.B               |
 | 6 | A.B.C             |
 | 7 | X                 |
 | 8 | X.Y               |
 | 9 | X.Y.Z             |
 +-----------------------+

我如何使用 PHP 执行此操作?

编辑:

我目前的"解决方案/尝试"

<?php
$arr = array(
    "a",
    "a.b",
    "a.b.c",
    "x",
    "x.y",
    "x.y.z",
);
$container = array();
$updateMe = array();
foreach($arr as $key => $value) {
    $cleanName = explode(".", $value);
    foreach($cleanName as $keyArray => $valueArray) {
        for($c = 0;$c<$keyArray+1;$c++) {
            $updateMe[$cleanName[$c]] = array();
        }

    } 
    $container[$cleanName[0]] = $updateMe;
    unset($updateMe);
}
echo "<pre>";
var_dump($container);
echo "==='r'n";

我的输出:

array(2) {
  ["a"]=>
  array(3) {
    ["a"]=>
    array(0) {
    }
    ["b"]=>
    array(0) {
    }
    ["c"]=>
    array(0) {
    }
  }
  ["x"]=>
  array(3) {
    ["x"]=>
    array(0) {
    }
    ["y"]=>
    array(0) {
    }
    ["z"]=>
    array(0) {
    }
  }
}
===

溶液

<?php
$arr = array(
    "a",
    "a.b",
    "a.b.c",
    "x",
    "x.y",
    "x.y.z",
);
$array = array();
$test = array();
foreach($arr as $key => $text) {
    $array = array();
    foreach(array_reverse(explode('.', $text)) as $key) $array = array($key => $array);
    $test[] = $array;
}
echo "<pre>";
var_dump($test);
echo "==='r'n";

我喜欢在PHP中使用引用。 这可能不是最好的解决方案,但它似乎有效。

<?php
$arr = array(
    "a",
    "a.b",
    "a.b.c",
    "x",
    "x.y",
    "x.y.z",
);
$output = array();
foreach($arr as $path){
    // Create a reference to the array
    // As we go deeper into the path we will move this reference down
    $setArray =& $output;
    foreach(explode('.', $path) as $key){
        // If this key does not exist, create it
        if(!isset($setArray[$key])){
            $setArray[$key] = array();
        }
        // Move the reference down one level,
        // so that the next iteration will create
        // the key at the right level
        $setArray =& $setArray[$key];
    }
}
// Destroy the reference, so that we don't accidently write to it later
unset($setArray);
var_dump($output);
您可以使用

此问题中接受的答案,也可以使用同一问题的此答案来获得一个良好的起点(我将使用第二个答案,因为在本例中它更短)。

$out = array();
foreach ($a as $string) {
    $array = array();
    foreach(array_reverse(explode('.', $string)) as $key) {
        $array = array($key => $array);
    }
    $out[] = $array;
}

这将为您提供一个基于数字键的数组,因此您可以使用以下问题的答案从数组的第一级移出:

$out = call_user_func_array('array_merge', $out);

而您的结果:

Array
(
    [a] => Array
        (
            [b] => Array
                (
                    [c] => Array
                        (
                        )
                )
        )
    [X] => Array
        (
            [Y] => Array
                (
                    [Z] => Array
                        (
                        )
                )
        )
)

这应该适合您:

<?php
    $a = array("a", "a.b", "a.b.c", "1", "1.2", "1.2.3");
    $results = array();
    function stringToArray($path) {
        $pos = strpos($path, ".");
        if ($pos === false)
            return array($path => "");
        $key = substr($path, 0, $pos);
        $path = substr($path, $pos + 1);
        return array(
            $key => stringToArray($path)
        );
    }
    foreach($a as $k => $v) {
        if(substr_count(implode(", ", $a), $v) == 1)
            $results[] = stringToArray($v);
    }
    $results = call_user_func_array('array_merge', $results);
    print_R($results);
?>

输出:

Array ( [a] => Array ( [b] => Array ( [c] => ) ) [0] => Array ( [2] => Array ( [3] => ) ) )

只是棘手的一个

  $a = array("a", "a.b", "a.b.c", "X", "X.Y", "X.Y.Z");
    $res = array();
    foreach ($a as $str) {
        $str = str_replace('.','"]["',$str);
        $tricky = '$res["'.$str.'"]';
        eval ($tricky.' = array();');
};