向分层 multi-dimensional 数组再添加一层

adding one more level to a hierarchical multi-dimensional array

更新:

这是从 mysql 获取的平面数组。我使用闭包 table 来存储层次关系:

Array
(
    [0] => Array
        (
            [brand] => Intel
            [id] => 53
            [name] => CPU 1978
            [parent_id] => 0
        )

    [1] => Array
        (
             [brand] => Asus
             [id] => 537
             [name] => CPU 1999
             [parent_id] => 53
        )

    [2] => Array
        (
             [brand] => HTC
             [id] => 538
             [name] => CPU 1998
             [parent_id] => 53
        )
)

我有一些数据显示新产品基于哪些古代产品。我正在使用以下代码将平面数组转换为分层数组,multi-dimensional 数组:

function buildTree(array $elements, $parentId = 0) {
 $branch = array();

 foreach ($elements as $element) {
    if ($element['parent_id'] == $parentId) {
        $children = buildTree($elements, $element['id']);
        if ($children) {
            $element['children'] = $children;
        }
        $branch[] = $element;
    }
 }

 return $branch;
}

结果:

Array
(
    [0] => Array
        (
            [brand] => Intel
            [id] => 53
            [name] => CPU 1978
            [parent_id] => 0
            [children] => Array
                (
                    [0] => Array
                        (
                            [brand] => Asus
                            [id] => 537
                            [name] => CPU 1999
                            [parent_id] => 53
                        )

                    [1] => Array
                        (
                            [brand] => HTC
                            [id] => 538
                            [name] => CPU 1998
                            [parent_id] => 53
                        )

                )

        )

)

我想通过向第一级添加新键 brands 来重组树,并将 children 的品牌提取为第二级的数组键,如下所示:

Array
(
    [0] => Array
        (
            [brand] => Intel
            [id] => 53
            [name] => CPU 1978
            [parent_id] => 0
            [brands]=> Array
                    (
                      [Asus]=> Array
                           (
                             [0] => Array
                             (
                               [id] => 537
                               [name] => CPU 1999
                               [parent_id] => 53
                             )
                           )

                      [HTC] => Array
                          (
                            [0]=>Array
                              (
                                [id] => 538
                                [name] => CPU 1998
                                [parent_id] => 53
                              )
                          )
                      [Intel]=>Array() // Keep this one for new CPU from Intel
                    )


        )

)

我已经尝试再创建一个函数来将品牌插入 parent 级别,但我的问题是,如何将 children 的 CPU 放入它们对应的级别品牌?

function brand(array $elements,$children){
  $branch = array();
  foreach($elements as $k=>$element){          
    /* if($element['brand'] == $children['brand']) not working **/
     $branch[$element['brand']] = $children;
  }
  return $branch;
}

function buildTree(array $elements, $parentId = 0) {
 $branch = array();

 foreach ($elements as $element) {
    if ($element['parent_id'] == $parentId) {
        $children = buildTree($elements, $element['id']);
        if ($children) {
            $element['brands'] = brand($elements,$children);

        }
        $branch[] = $element;
    }
 }

 return $branch;
}

这给了我这个结果:

 Array
    (
        [0] => Array
            (
                [brand] => Intel
                [id] => 53
                [name] => CPU 1978
                [parent_id] => 0
                [brands]=> Array
                        (
                          [Asus]=> Array
                               (
                                 [0] => Array
                                 (
                                   [brand]=> Asus
                                   [id] => 537
                                   [name] => CPU 1999
                                   [parent_id] => 53
                                 )
                                 [1]=>Array
                                  (
                                    [brand]=>HTC
                                    [id] => 538
                                    [name] => CPU 1998
                                    [parent_id] => 53
                                  )
                               )

                          [HTC] => Array
                              (
                                 [0] => Array
                                 (
                                   [brand]=> Asus
                                   [id] => 537
                                   [name] => CPU 1999
                                   [parent_id] => 53
                                 )
                                  [1]=>Array
                                  (
                                    [brand]=>HTC
                                    [id] => 538
                                    [name] => CPU 1998
                                    [parent_id] => 53
                                  )
                              )
                          [Intel]=>Array(
                              (
                                 [0] => Array
                                 (
                                   [brand]=> Asus
                                   [id] => 537
                                   [name] => CPU 1999
                                   [parent_id] => 53
                                 )
                                  [1]=>Array
                                  (
                                    [brand]=>HTC
                                    [id] => 538
                                    [name] => CPU 1998
                                    [parent_id] => 53
                                  )
                              )
                           )
                      )


            )

    )

编辑:当一个品牌有多个子元素时,我之前的回答严重失败。下面是一个更强大的解决方案。

function buildTree(array $elements, $parentId = 0)
{
    $branch = [];

    foreach ($elements as $element) {
        if ($element['parent_id'] == $parentId) {
            $element['brands'] = brand(buildTree($elements, $element['id']));

            $branch[] = $element;
        }
    }

    return $branch;
}

function brand(array $elements)
{
    $branch = [];
    foreach ($elements as $element) {
        $branch[$element['brand']][] = [
            'id' => $element['id'],
            'name' => $element['name'],
            'parent_id' => $element['parent_id'],
        ];
    }

    return $branch;
}

这个returns下面的原始数组:

Array
(
    [0] => Array
        (
            [brand] => Intel
            [id] => 53
            [name] => CPU 1978
            [parent_id] => 0
            [brands] => Array
                (
                    [Asus] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 537
                                    [name] => CPU 1999
                                    [parent_id] => 53
                                )
                        )
                    [HTC] => Array
                        (
                            [0] => Array
                                (
                                    [id] => 538
                                    [name] => CPU 1998
                                    [parent_id] => 53
                                )
                        )
                )
        )
)

RedGiant,以下函数将获取现有 buildTree() 方法的输出并以递归方式对其进行转换,使得数组树中的所有 children 元素都将替换为 brands:

function brand(array $elements)
{
    // Return early if parent has no children
    if (! array_key_exists('children', $elements)) {
        return $elements;
    }

    // Initialise local values
    $brands = array();

    // Transform children (recursively)
    foreach ((array) $elements['children'] as $child) {
        $brand = $child['brand'];
        unset($child['brand']);

        // Use call_user_func() and __function__ to prevent name dependency
        // within the function itself. If required, this can be replaced with:
        // $brands[$brand] = array(brand($child);
        $brands[$brand] = array(call_user_func(__function__, $child));
    }

    // Replace children with brands
    unset($elements['children']);
    $elements['brands'] = $brands;

    return $elements;
}

函数应该通过array_map()调用,即:

$old_tree = buildTree($original_flat_array)
$new_tree = array_map('brand', buildTree($original_flat_array));

这个解决方案的优点是它保留了所有现有的数组键(显然 children 除外)。因此,您将来可能添加到原始平面数组中的任何键都将被带入新的转换后的数组树中,而无需修改代码。