English 中文(简体)
在PHP[复制]的一个固定阵列上植树
原标题:Build a tree from a flat array in PHP [duplicate]

我看着互联网,发现我所期待的东西。 我有一个固定的阵列,每个元素都含有id和 parent。 每个单元只有单亲,但可能有多个子女。 如果母体=0,则被视为一个基本项目。 我试图把我的平整阵带上树。 我发现的其他样本只向父母复制了该元素,但原样仍然存在。

http://www.ohchr.org。

起始阵列的每个组成部分都从单独的XML档案中阅读。 档案本身如无父母,其价值为0。 关键因素实际上是在扼杀。

我对先前的混乱感到担忧。 希望这一点更为明确:

http://www.ohchr.org。

我的起点是:

Array
(
    [_319_] => Array
        (
            [id] => 0
            [parent_id] => 0
        )

    [_320_] => Array
        (
            [id] => _320_
            [parent_id] => 0
        )

    [_321_] => Array
        (
            [id] => _321_
            [parent_id] => _320_
        )

    [_322_] => Array
        (
            [id] => _322_
            [parent_id] => _321_
        )

    [_323_] => Array
        (
            [id] => _323_
            [parent_id] => 0
        )

    [_324_] => Array
        (
            [id] => _324_
            [parent_id] => _323_
        )

    [_325_] => Array
        (
            [id] => _325_
            [parent_id] => _320_
        )
)

树后形成的阵列:

Array
(
    [_319_] => Array
        (
            [id] => _319_
            [parent_id] => 0
        )

    [_320_] => Array
        (
            [id] => _320_
            [parent_id] => 0
            [children] => Array
                (
                    [_321_] => Array
                        (
                            [id] => _321_
                            [parent_id] => _320_
                            [children] => Array
                                (
                                    [_322_] => Array
                                        (
                                            [id] => _322_
                                            [parent_id] => _321_
                                        )
                                )
                        )
                    [_325_] => Array
                        (
                            [id] => _325_
                            [parent_id] => _320_
                        )
                )
    [_323_] => Array
        (
            [id] => _323_
            [parent_id] => 0
            [children] => Array
                (
                    [_324_] => Array
                        (
                            [id] => _324_
                            [parent_id] => _323_
                        )
                )
        )

任何帮助/指导都受到高度赞赏。

我迄今为止的一些法典:


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

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

        return $branch;
    }

最佳回答

You forgot the unset() in there bro.

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[ id ]] = $element;
            unset($elements[$element[ id ]]);
        }
    }
    return $branch;
}
问题回答

然而,正如 m夫指出的,ImmortalFirefly的解决办法并不挽救没有子女的父母。 I ve edited the function tofix this issue:

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[ id ]] = $element;
            unset($element);
        }
    }
    return $branch;
}

对我来说,这项工作是:

$index=array();
$tree=array();
foreach ($ori as $key=>$var) {
  $var=array_shift($ori);
  if ($var[ id ]==0) $var[ id ]=$key;
  if ((string)$var[ parent_id ]=== 0 ) {
    $tree[$key]=$var;
    $index[$key]=&$tree[$key];
  } else if (isset($index[$var[ parent_id ]])) {
    if (!isset($index[$var[ parent_id ]][ children ])) $index[$var[ parent_id ]][ children ]=array();
    $index[$var[ parent_id ]][ children ][$key]=$var;
    $index[$key]=&$index[$var[ parent_id ]][ children ][$key];
  } else {
    array_push($ori,$var);
  }
}
unset($index);
print_r($tree);

我可以看到逻辑,但结果是:

Array
(
    [0] => Array
        (
            [id] => 0
            [parent_id] => 0
        )

    [1] => Array
        (
            [id] => 1
            [parent_id] => 0
        )

IMHO, is parent_id = o, shouldn t *** be a child of [0] here?

Anyway, references to the rescue:

$tree = array();
foreach($inputarray as $item){
     if(!isset($tree[$item[ id ]])) $tree[$item[ id ]] = array();
     $tree[$item[ id ]] = array_merge($tree[$item[ id ]],$item);
     if(!isset($tree[$item[ parent_id ]])) $tree[$item[ parent_id ]] = array();
     if(!isset($tree[$item[ parent_id ]][ children ])) $tree[$item[ parent_id ]][ children ] = array();
     $tree[$item[ parent_id ]][ children ][] = &$tree[$item[ id ]];
}
$result = $tree[0][ children ];
unset($tree);
print_r($result);

Because you have abused 0 as both a magic number as root, and an existing id, we now have recursion in the id=0 branch. Adding if($item[ parent_id ]!=$item[ id ]) before $tree[$item[ parent_id ]][ children ][] = &$tree[$item[ id ]]; could prevent that, but it isn t pretty.

可能建造来源阵列,但你可以使用这一功能(表面上——id,id, 标题):

$q = mysql_query("SELECT id, parent_id, name FROM categories");
while ($r = mysql_fetch_row($q)) {
  $names[$r[0]] = $r[2];
  $children[$r[0]][] = $r[1];
 }

function render_select($root=0, $level=-1) {
  global $names, $children;
  if ($root != 0)
    echo  <option>  . strrep(   , $level) . $names[$root] .  </option> ;
  foreach ($children[$root] as $child)
    render_select($child, $level+1);
}

echo  <select> ;
render_select();
echo  </select> ;
  1. More efficient hierarchy system

Though this is an old question, I m gonna post my answer here:

/* assuming top level pid = 0 */
$rows = array (
    array (  id  => 1,  pid  => 0 ),
    /* ... */
);

/* make id become array key */
$rows = array_column ( $rows, null,  id  ); 

foreach ( $rows as $key => $val ) {
    if ( $val [ pid ] ) {
        if ( isset ( $rows [$val [ pid ]] )) {
            $rows [$val [ pid ]][ children ][] = &$rows [$key];
        }
    }
}

foreach ( $rows as $key => $val ) {
    if ( $val [ pid ] ) unset ( $rows [$key] );
}

array_column> 是PHP.5,但你可以方便地自行选择。

这是我的解决办法、复制和优化其他解决办法。

function buildTree(array &$elements, $parentId = 0) {
    $branch = array();
    foreach ($elements as $key => $element) {
        if ($element[ parent_id ] == $parentId) {
            $children = $this->buildTree($elements, $key);
            if ($children) {
                $element[ children ] = $children;
            }
            $branch[$key] = $element;
            unset($elements[$key]);
        }
    }
    return $branch;
}

你们想看一下在我的SQL中储存和装上等级数据的问题,因为我要解决几个问题。 我假定第一个阵列是数据库直接提供的数据吗?

It looks like you re trying to use the adjacency model to organize your data into the hierarchy structure. There are also other ways to achieve this using nesting. If you are not taking this data from a database then this may not be as useful.

这一联系应有助于您:http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/“rel=“nofollow”http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

SteveEdson的代码进行罚款,除非在原始数据结构中不存在元素的母体。 这里,我要指出这一点(不管怎么说,它从内容中删除了“表面上”的内容,这些要素可能或不可能被接受):

function buildTree(array &$elements, $parentId = 0)
{
    $branch = array();
    foreach ($elements as &$element) {
        if ($element["parent_id"] != null && $elements[$element["parent_id"]] == null)
            unset($element["parent_id"]);        
        if ($element[ parent_id ] == $parentId) {
            $children = buildTree($elements, $element[ id ]);
            if ($children) {
                $element[ children ] = $children;
            }
            $branch[$element[ id ]] = $element;
            unset($element);
        }
    }
    return $branch;
}

我的解决办法是:首先,然后,通过<条码> 括号-id把所有儿童分到一起,使用分类清单进行照料。

public function get_nested_tree() {
    $parent_node = null;
    $nodes_by_parent = array();
    
    if(is_null($flat_list) || count($flat_list) <= 0){
        return null;
    }

    foreach ($flat_list as $node) {
        if($node[ parent_id ] != null){
            $nodes_by_parent[$node[ parent_id ]][] = $node;
        }
        else{
            // NB. In my implementation if multiple roots exist,
            // I want to always return the first...
            if(is_null($parent_node)){
                $parent_node = $node;
            }
        }
    }

    return $this->populate_branch($parent_node, $nodes_by_parent);
}

public function populate_branch($node, $nodes_by_parent){
    $children = $nodes_by_parent[$node[ id ]] ?? [];

    foreach ($children as &$child){
        $child = $this->populate_branch($child, $nodes_by_parent);
    }

    $node[ children ] = $children;

    return $node;
}

我认为,时间的复杂性是线性(O(n))——假设PHP的关联阵列相当于>其他语文的密码>。

在这里,我的解决办法是理想的,如果我们假设最高层的母子_id=0:

function MakeTree($arr){
    $parents_arr=array();
    foreach ($arr as $key => $value) {
        $parents_arr[$value[ pid ]][$value[ id ]]=$value;
    }
    $tree=$parents_arr[ 0 ];
    $this->createTree($tree, $parents_arr);
    return $tree;
}
function createTree(&$tree, $parents_arr){
    foreach ($tree as $key => $value) {
        if(!isset($value[ children ])) {
            $tree[$key][ children ]=array();
        }
        if(array_key_exists($key, $parents_arr)){
            $tree[$key][ children ]=$parents_arr[$key];
            $this->createTree($tree[$key][ children ], $parents_arr);
        }
    }
}

清洁、短、无压。 树阵列:

class Mother {
    private $root;
    public function treeInit($array)
    {
        $this->root = new Child();
        foreach($array as $value){
            $this->root->treeClimb(array_reverse($value));
        }
        return $this->root;
    }
}

class Child {
    private $children = [];
    public function treeClimb($arr)
    {
        if(count($arr) > 0) {
            $childTmp = array_pop($arr);
            if(!key_exists($childTmp,$this->children))
            {
                $this->children[$childTmp] = new Child();
            }
        $this->children[$childTmp]->treeClimb($arr);
        }
    }
}

$array = array(array( obst , banae , krumm , gelb ),
                    array( obst , beere , him ),
                    array( obst , beere , brom ),
                    array( obst , banae , gerade ),
                    array( veg , carot , gerade ));

$obj = new Mother();
var_dump($obj->treeInit($array));

我提出了与“@eugen-rieck”类似的解决办法,希望分享。 不过,我称之为<代码>$branches

$tree = [];
$branches = [];

while (!empty($input)) {
    $beforeCount = count($input);

    foreach ($input as $id => $item) {
        $pid = $item[ parent_id ];

        if (isset($branches[$pid])) {
            $branches[$pid][ children ][$id] = $item;
            $branches[$id] = &$branches[$pid][ children ][$id];
            unset($input[$id]);
        }
    }

    if ($beforeCount === count($input)) {
        $firstItem = array_shift($input);
        $id = $firstItem[ id ];
        $tree[$id] = $firstItem;
        $branches[$id] = &$tree[$id];
    }
}

在Laravel,这一法典帮助我

<?php
    
    namespace AppServices;
    
    use AppModelsCategoryModel;
    
    class CategoryService
    {
        
        public function getTree(): array
        {
            $categories = CategoryModel::query()->orderBy( sort_category )
                ->select([ id ,  title ,  slug ,  image , parent_id ])
                ->get()->toArray();
            return $this->generateTree($categories);
        }
    
        public function generateTree($elements, $parentId = 0): array
        {
            $result = [];
            foreach ($elements as $element) {
                if ($element[ parent_id ] == $parentId) {
                    $children = $this->generateTree($elements, $element[ id ]);
                    if ($children) {
                        $element[ children ] = $children;
                    }
                    $result[$element[ id ]] = $element;
                    unset($elements[$element[ id ]]);
                }
            }
            return $result;
        }
    }




相关问题
Brute-force/DoS prevention in PHP [closed]

I am trying to write a script to prevent brute-force login attempts in a website I m building. The logic goes something like this: User sends login information. Check if username and password is ...

please can anyone check this while loop and if condition

<?php $con=mysql_connect("localhost","mts","mts"); if(!con) { die( unable to connect . mysql_error()); } mysql_select_db("mts",$con); /* date_default_timezone_set ("Asia/Calcutta"); $date = ...

定值美元

如何确认来自正确来源的数字。

Generating a drop down list of timezones with PHP

Most sites need some way to show the dates on the site in the users preferred timezone. Below are two lists that I found and then one method using the built in PHP DateTime class in PHP 5. I need ...

Text as watermarking in PHP

I want to create text as a watermark for an image. the water mark should have the following properties front: Impact color: white opacity: 31% Font style: regular, bold Bevel and Emboss size: 30 ...

How does php cast boolean variables?

How does php cast boolean variables? I was trying to save a boolean value to an array: $result["Users"]["is_login"] = true; but when I use debug the is_login value is blank. and when I do ...

热门标签