优雅地将平面数组分解为嵌套关联数组


Elegantly exploding flat array to a nested associative array?

我有一个 API 调用的返回,该调用将类别树作为平面数组提供,其中父/子关系用重复的字符串拼写出来。 一个小样本:

                [0] => Architecture & Street Scenes
                [1] => Architecture & Street Scenes/Architectural Detail
                [2] => Architecture & Street Scenes/Architectural Detail/Cast or Wrought Ironwork
                [3] => Architecture & Street Scenes/Architectural Detail/Cast or Wrought Ironwork/Balconies
                [4] => Architecture & Street Scenes/Architectural Detail/Cast or Wrought Ironwork/Fences
                [5] => Architecture & Street Scenes/Courtyards
                [6] => Architecture & Street Scenes/Exteriors & Street Scenes
                [7] => Architecture & Street Scenes/Interiors
                [8] => Architecture & Street Scenes/Street Lamps
                [9] => Art & Culture
                [10] => Art & Culture/Dance

有没有一种优雅的方法使用 PHP 从那里开始消除重复并通过拥有子数组来表达关系?

                    [0] => Architecture & Street Scenes
                      [0] => Architectural Detail
                        [0] => Cast or Wrought Ironwork
                        [1] => Cast or Wrought Ironwork
                            [0] => Balconies
                            [1] => Fences
                      [1] => Courtyards
                      [2] => Exteriors & Street Scenes
                      [3] => Interiors
                      [4] => Street Lamps
                    [1] => Art & Culture
                        [0] => Dance

我的想法是,您将每个令牌用作创建哈希表的键。

<?php
$api = array(
    "Architecture & Street Scenes",
    "Architecture & Street Scenes/Architectural Detail",
    "Architecture & Street Scenes/Architectural Detail/Cast or Wrought Ironwork",
    "Architecture & Street Scenes/Architectural Detail/Cast or Wrought Ironwork/Balconies",
    "Architecture & Street Scenes/Architectural Detail/Cast or Wrought Ironwork/Fences",
    "Architecture & Street Scenes/Courtyards",
    "Architecture & Street Scenes/Exteriors & Street Scenes",
    "Architecture & Street Scenes/Interiors",
    "Architecture & Street Scenes/Street Lamps",
    "Art & Culture",
    "Art & Culture/Dance",
);
$end = array();
foreach ($api as $v) {
    $tokens = explode('/', $v);
    $parent = &$end;
    foreach ($tokens as $token) {
        if (!array_key_exists($token, $parent)) {
            $parent[$token] = array();
        }
        $parent = &$parent[$token];
    }
}
print_r($end);

输出:

Array
(
    [Architecture & Street Scenes] => Array
        (
            [Architectural Detail] => Array
                (
                    [Cast or Wrought Ironwork] => Array
                        (
                            [Balconies] => Array
                                (
                                )
                            [Fences] => Array
                                (
                                )
                        )
                )
            [Courtyards] => Array
                (
                )
            [Exteriors & Street Scenes] => Array
                (
                )
            [Interiors] => Array
                (
                )
            [Street Lamps] => Array
                (
                )
        )
    [Art & Culture] => Array
        (
            [Dance] => Array
                (
                )
        )
)

因此,当您迭代它们时,您可以执行以下操作:

foreach ($end as $k => $v) {
    echo $k; //Here is your top level element.
    //You'd then iterate through it's children which are in $v.
}

有几种方法可以做到这一点,这里有一个递归选项,无论输入数据的顺序如何,它都会实现相同的目标。

$output = array();
foreach($api_data as $line){
    process_children($line, $output);
}
function process_children($line, &$output){
    $split = explode('/', $line, 2);
    if(!isset($output[$split[0]]))
        $output[$split[0]] = array();
    if(isset($split[1]))
        process_children($split[1], $output[$split[0]]);
}
print_r($output);