如何从数据库构建“子父”树/嵌套数组


How to build a "child-parent" tree/nested array from database?

表"人"+----+------------+-------+|锡 |姓名 |鞋面 |+----+------------+-------+| 1 |克莱门特 |    0 || 2 |吉恩 |    1 || 3 |安妮 |    1 || 4 |袁 |    2 || 5 |梅 |    2 || 6 |蓝色 |    3 || 7 |杨 |    5 || 8 |洛琳达 |    0 |+----+------------+-------+

结构是这样的:

克莱门特    珍        元        美            阳    安妮          蓝洛琳达

upper列说明了他/她自己的上位人。

问题是:如何从 MySQL 获取嵌套/多维数组?我以为我可以使用循环来获取,但我未能自动获取所有低音。数组可以是这样的:

数组(    [1]=>数组    (        [自我]=>克莱门特        [2]=>数组        (            [自我]=>让            [4]=>数组            (                [自我]=>元            )            [5]=>数组            (                [自我]=>美                [7]=>数组                (                    [自我]=>阳                )            )        )        [3]=>数组        (            [自我]=>安妮            [6]=>数组            (                [自我]=>蓝色            )        )    )    [8]=>数组    (        [自我]=>洛琳达    ))

由于我们不知道一个人有多少"上层"人员,因此解决方案应该是一个自动化功能,可以构建一个完整的阵列,而不仅仅是三维或四维。换句话说,该功能应该从高层深入到所有下层的人。

给定您的输入:

$input = array(
  array('sn' => 1, 'name' => 'Clement', 'upper' => 0),
  array('sn' => 2, 'name' => 'Jean',    'upper' => 1),
  array('sn' => 3, 'name' => 'Annie',   'upper' => 1),
  array('sn' => 4, 'name' => 'Yuan',    'upper' => 2),
  array('sn' => 5, 'name' => 'Mei',     'upper' => 2),
  array('sn' => 6, 'name' => 'Blue',    'upper' => 3),
  array('sn' => 7, 'name' => 'Yang',    'upper' => 5),
  array('sn' => 8, 'name' => 'Lorinda', 'upper' => 0),
);

使用引用,您可以使用以下循环构建树:

$map = array();
foreach ($input as $node) {
  // init self
  if (!array_key_exists($node['sn'], $map)) {
    $map[$node['sn']] = array('self' => $node['name']);
  }
  else {
    $map[$node['sn']]['self'] = $node['name'];
  }
  // init parent
  if (!array_key_exists($node['upper'], $map)) {
    $map[$node['upper']] = array();
  }
  // add to parent
  $map[$node['upper']][$node['sn']] = & $map[$node['sn']];
}
print_r($map[0]);

演示:http://3v4l.org/vuVPu

假设数据是这样的

$data = array(
    array(1, 'Clement', 0),
    array(2, 'Jean   ', 1),
    array(3, 'Annie  ', 1),
    array(4, 'Yuan   ', 2),
    array(5, 'Mei    ', 2),
    array(6, 'Blue   ', 3),
    array(7, 'Yang   ', 5),
    array(8, 'Lorinda', 0),
);

此递归函数可能有效:

function tree($data, $node) {
    foreach($data as $e)
        if($e[2] == $node[0])
            $node['children'] []= tree($data, $e);
    return $node;
}

像这样使用它:

$tree = tree($data, array(0));
print_r($tree);

使用参考地图

$input = array(
  array('sn' => 1, 'name' => 'Clement', 'upper' => 0),
  array('sn' => 2, 'name' => 'Jean',    'upper' => 1),
  array('sn' => 3, 'name' => 'Annie',   'upper' => 1),
  array('sn' => 4, 'name' => 'Yuan',    'upper' => 2),
  array('sn' => 5, 'name' => 'Mei',     'upper' => 2),
  array('sn' => 6, 'name' => 'Blue',    'upper' => 3),
  array('sn' => 7, 'name' => 'Yang',    'upper' => 5),
  array('sn' => 8, 'name' => 'Lorinda', 'upper' => 0),
);
$map = []; // map a reference by id for each item
foreach ($input as &$inp) {
  $map[$inp['sn']] = &$inp;
}
foreach ($map as &$_inp) { // assign each item to its parent, with help of the map
  if ($_inp['upper']) {
    $map[$_inp['upper']]['children'] = &$map[$_inp['upper']]['children'] ?? [];
    $map[$_inp['upper']]['children'][] = &$_inp;
  }
}
$result = array_filter($map, fn($item) => !$item['upper']);
print_r($result);```