可能的重复项:
根据父 ID 值将数组从一维转换为多维
我在PHP工作。
我有以下具有关系数据(父子关系)的数组。
Array
(
[5273] => Array
(
[id] => 5273
[name] => John Doe
[parent] =>
)
[6032] => Array
(
[id] => 6032
[name] => Sally Smith
[parent] => 5273
)
[6034] => Array
(
[id] => 6034
[name] => Mike Jones
[parent] => 6032
)
[6035] => Array
(
[id] => 6035
[name] => Jason Williams
[parent] => 6034
)
[6036] => Array
(
[id] => 6036
[name] => Sara Johnson
[parent] => 5273
)
[6037] => Array
(
[id] => 6037
[name] => Dave Wilson
[parent] => 5273
)
[6038] => Array
(
[id] => 6038
[name] => Amy Martin
[parent] => 6037
)
)
我需要它采用这种 JSON 格式:
{
"id":"5273",
"name":"John Doe",
"data":{
},
"children":[
{
"id":" Sally Smith",
"name":"6032",
"data":{
},
"children":[
{
"id":"6034",
"name":"Mike Jones",
"data":{
},
"children":[
{
"id":"6035",
"name":"Jason Williams",
"data":{
},
"children":[
{
"id":"node46",
"name":"4.6",
"data":{
},
"children":[
]
}
]
}
]
},
{
"id":"6036",
"name":"Sara Johnson",
"data":{
},
"children":[
]
},
{
"id":"6037",
"name":"Dave Wilson",
"data":{
},
"children":[
{
"id":"6038",
"name":"Amy Martin",
"data":{
},
"children":[
]
}
]
}
]
}
]
}
我知道我需要创建一个多维数组并通过 json_encode() 运行它。我还认为,用于执行此操作的这种方法必须是递归的,因为现实世界的数据可能具有未知数量的级别。
我很乐意展示我的一些方法,但它们没有奏效。
谁能帮我?
我被要求分享我的作品。这是我尝试过的,但我还没有那么接近我不知道它有多大帮助。
我做了一连串的关系。
foreach($array as $k => $v){
$relationships[$v['id']] = $v['parent'];
}
我认为(基于另一个 SO 帖子)使用此关系数据来创建一个新的多维数组。如果我让它工作,我将努力添加正确的"儿童"标签等。
$childrenTable = array();
$data = array();
foreach ($relationships as $n => $p) {
//parent was not seen before, put on root
if (!array_key_exists($p, $childrenTable)) {
$childrenTable[$p] = array();
$data[$p] = &$childrenTable[$p];
}
//child was not seen before
if (!array_key_exists($n, $childrenTable)) {
$childrenTable[$n] = array();
}
//root node has a parent after all, relocate
if (array_key_exists($n, $data)) {
unset($data[$n]);
}
$childrenTable[$p][$n] = &$childrenTable[$n];
}
unset($childrenTable);
print_r($data);
<?php
header('Content-Type: application/json; charset="utf-8"');
/**
* Helper function
*
* @param array $d flat data, implementing a id/parent id (adjacency list) structure
* @param mixed $r root id, node to return
* @param string $pk parent id index
* @param string $k id index
* @param string $c children index
* @return array
*/
function makeRecursive($d, $r = 0, $pk = 'parent', $k = 'id', $c = 'children') {
$m = array();
foreach ($d as $e) {
isset($m[$e[$pk]]) ?: $m[$e[$pk]] = array();
isset($m[$e[$k]]) ?: $m[$e[$k]] = array();
$m[$e[$pk]][] = array_merge($e, array($c => &$m[$e[$k]]));
}
return $m[$r][0]; // remove [0] if there could be more than one root nodes
}
echo json_encode(makeRecursive(array(
array('id' => 5273, 'parent' => 0, 'name' => 'John Doe'),
array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
)));
演示:https://3v4l.org/s2PNC
好的,这就是它的工作原理,你实际上在开始时并没有太远,但你实际寻找的是参考。这是一个常规过程:
由于父节点和子节点在其 ID 上存在关系,因此首先需要根据 ID 为数据编制索引。我在这里用一个数组($rows
)来模拟你的数据访问,如果你从数据库中读取,它会是类似的。通过此索引编制,您还可以添加其他属性,例如空数据:
// create an index on id
$index = array();
foreach($rows as $row)
{
$row['data'] = (object) array();
$index[$row['id']] = $row;
}
因此,现在所有条目都根据其 ID 编制索引。这是第一步。
第二步同样直截了当。因为我们现在可以根据每个节点在$index
中的 ID 访问每个节点,我们可以将子节点分配给它们的父节点。
有一个"虚拟"节点,即 ID 为 0 的节点。它不存在于任何行中,但是,如果我们也可以向其添加子项,则可以将此子集合用作所有根节点的存储区,在您的情况下,只有一个根节点。
当然,对于 ID 0
,我们不应该处理父级 - 因为它不存在。
所以让我们这样做。我们在这里使用引用,因为否则同一个节点不能同时是父节点和子节点:
// build the tree
foreach($index as $id => &$row)
{
if ($id === 0) continue;
$parent = $row['parent'];
$index[$parent]['children'][] = &$row;
}
unset($row);
因为我们使用引用,所以最后一行注意在循环后取消设置存储在$row
中的引用。
现在所有的孩子都被分配给他们的父母。这可能已经是了,但是不要忘记最后一步,应该访问输出的实际节点。
为简洁起见,只需将根节点分配给$index
本身。如果我们记得,我们想要的唯一根节点是 ID 为 0
的节点中子数组中的第一个根节点:
// obtain root node
$index = $index[0]['children'][0];
仅此而已。我们现在可以直接使用它来生成 JSON:
// output json
header('Content-Type: application/json');
echo json_encode($index);
最后整个代码一目了然:
<?php
/**
* @link http://stackoverflow.com/questions/11239652/php-create-a-multidimensional-array-from-an-array-with-relational-data
*/
$rows = array(
array('id' => 5273, 'parent' => 0, 'name' => 'John Doe'),
array('id' => 6032, 'parent' => 5273, 'name' => 'Sally Smith'),
array('id' => 6034, 'parent' => 6032, 'name' => 'Mike Jones'),
array('id' => 6035, 'parent' => 6034, 'name' => 'Jason Williams'),
array('id' => 6036, 'parent' => 5273, 'name' => 'Sara Johnson'),
array('id' => 6037, 'parent' => 5273, 'name' => 'Dave Wilson'),
array('id' => 6038, 'parent' => 6037, 'name' => 'Amy Martin'),
);
// create an index on id
$index = array();
foreach($rows as $row)
{
$row['data'] = (object) [];
$index[$row['id']] = $row;
}
// build the tree
foreach($index as $id => &$row)
{
if ($id === 0) continue;
$parent = $row['parent'];
$index[$parent]['children'][] = &$row;
}
unset($row);
// obtain root node
$index = $index[0]['children'][0];
// output json
header('Content-Type: application/json');
echo json_encode($index, JSON_PRETTY_PRINT);
这将创建以下 json(此处为 PHP 5.4s 的JSON_PRETTY_PRINT
):
{
"id": 5273,
"parent": 0,
"name": "John Doe",
"data": {
},
"children": [
{
"id": 6032,
"parent": 5273,
"name": "Sally Smith",
"data": {
},
"children": [
{
"id": 6034,
"parent": 6032,
"name": "Mike Jones",
"data": {
},
"children": [
{
"id": 6035,
"parent": 6034,
"name": "Jason Williams",
"data": {
}
}
]
}
]
},
{
"id": 6036,
"parent": 5273,
"name": "Sara Johnson",
"data": {
}
},
{
"id": 6037,
"parent": 5273,
"name": "Dave Wilson",
"data": {
},
"children": [
{
"id": 6038,
"parent": 6037,
"name": "Amy Martin",
"data": {
}
}
]
}
]
}
以下代码将完成这项工作.. 您可能需要根据需要稍作调整。
$data = array(
'5273' => array( 'id' =>5273, 'name'=> 'John Doe', 'parent'=>''),
'6032' => array( 'id' =>6032, 'name'=> 'Sally Smith', 'parent'=>'5273'),
'6034' => array( 'id' =>6034, 'name'=> 'Mike Jones ', 'parent'=>'6032'),
'6035' => array( 'id' =>6035, 'name'=> 'Jason Williams', 'parent'=>'6034')
);
$fdata = array();
function ConvertToMulti($data) {
global $fdata;
foreach($data as $k => $v)
{
if(empty($v['parent'])){
unset($v['parent']);
$v['data'] = array();
$v['children'] = array();
$fdata[] = $v;
}
else {
findParentAndInsert($v, $fdata);
}
}
}
function findParentAndInsert($idata, &$ldata) {
foreach ($ldata as $k=>$v) {
if($ldata[$k]['id'] == $idata['parent']) {
unset($idata['parent']);
$idata['data'] = array();
$idata['children'] = array();
$ldata[$k]['children'][] = $idata;
return;
}
else if(!empty($v['children']))
findParentAndInsert($idata, $ldata[$k]['children']);
}
}
print_r($data);
ConvertToMulti($data);
echo "AFTER'n";
print_r($fdata);
http://codepad.viper-7.com/Q5Buaz