PHP 构建多层树的逻辑

PHP logic to build multi level tree

已更新

我有以下数组,例如:

[{id:1},{id:2}{id:3},{id:4},{id:5},...{id:20}]

请问如何生成如下图的JSONobject,才能在图1中实现下面的树?它不需要 parent id,因为它是先到先得,每个节点只会有直接的 3 个孩子。

我认为它将 运行 通过函数并将 children 附加到 object。我也希望将来控制孩子的数量。提前致谢

JSON object

{
    "tree": {
        "id": 1,
        "children": [
            {
                "id": 2,
                "children": [
                    {
                        "id": 5,
                        "children": [
                            {
                                "id": 11
                            },
                            {
                                "id": 12
                            },
                            {
                                "id": 13
                            }
                        ]
                    },
                    {
                        "id": 6
                    },
                    {
                        "id": 7
                    }
                ]
            },
            {
                "id": 3,
                "children": [
                    {
                        "id": 8
                    },
                    {
                        "id": 9
                    },
                    {
                        "id": 10
                    }
                ]
            },
            {
                "id": 4,
                "children": [
                    {
                        "id": 11
                    },
                    {
                        "id": 12
                    },
                    {
                        "id": 13
                    }
                ]
            }
        ]
    }
}

图 1:树图

首先,您的 JSON 对象包含重复的 ID。

所以逻辑是 - 取第一个元素,将其标记为 current_parent。每个后续元素都放入 parents_queue 并放入 current_parent 子数组。如果 current_parent 子数组长度为 3 个元素,则从 parents_queue 中取出下一个节点并将其标记为 current_parent。 示例代码:

// Generate test data
$data = [];
foreach(range(1,20) as $i)
  $data[] = ['id' => $i];

// Tree root and helper vars
$root = null;
$current_parent_node_pointer = null;
$parents_queue = [];

for( $i = 0; $i < count($data); $i++ ){

  $node = &$data[$i];

  // Not the first element
  if( $i ){
    
    if( empty( $current_parent_node_pointer['children'] ) )
      $current_parent_node_pointer['children'] = [];

    // Add the node to current parent
    $current_parent_node_pointer['children'][] = &$node;

    // Current parent has 3 children now, take a new one from the queue;
    if( count( $current_parent_node_pointer['children'] ) == 3 ){
      unset($current_parent_node_pointer); // destroy the reference before assining a new value
      $current_parent_node_pointer = &$parents_queue[0];
      array_shift($parents_queue); // remove current parent from the queue
    }

    // Add current node to the parents queue
    $parents_queue[] = &$node;

  }
  // First element; actually an initialization
  else {
    $root = &$node;
    $current_parent_node_pointer = &$node;
  }
}

$json = json_encode( ['tree' => $root] );

UPD:如果你的输入是一个对象数组,代码会稍微简单一些(不需要引用用法):

// Generate test data
$data = [];
foreach(range(1,20) as $i)
  $data[] = (object)['id' => $i];

// Tree root and helper vars
$root = null;
$current_parent_node_pointer = null;
$parents_queue = [];

foreach($data as $node){

  // Not the first element
  if( !empty($current_parent_node_pointer) ){
    
    if( empty( $current_parent_node_pointer->children ) )
      $current_parent_node_pointer->children = [];

    // Add the node to current parent
    $current_parent_node_pointer->children[] = $node;

    // Current parent has 3 children now, take a new one from the queue;
    if( count( $current_parent_node_pointer->children ) == 3 )
      $current_parent_node_pointer = array_shift($parents_queue);

    // Add current node to the parents queue
    $parents_queue[] = $node;

  }
  // First element; actually an initialization
  else {
    $root = $node;
    $current_parent_node_pointer = $node;
  }
}

$json = json_encode( ['tree' => $root] );