Home >Backend Development >PHP Tutorial >如何将数组中含有从属关系的元素重新排列

如何将数组中含有从属关系的元素重新排列

WBOY
WBOYOriginal
2016-06-06 20:30:251060browse

从数据表里取得一组二维数组,每个元素有键为 id 和 pid 的值,在不使用递归的情况下,如何按照其 pid 的值将元素移入到相应 id 元素中成为其子元素?

<code>array(6) {
  [0] => array(3) {
    ["id"]   =>  "21"
    ["pid"]  =>  "0"
    ["name"] =>  "aaa"
  }
  [1] => array(3) {
    ["id"]   =>  "22"
    ["pid"]  =>  "0"
    ["name"] =>  "bbb"
  }
  [2] => array(3) {
    ["id"]   =>  "23"
    ["pid"]  =>  "0"
    ["name"] =>  "ccc"
  }
  [3] => array(3) {
    ["id"]   =>  "24"
    ["pid"]  =>  "23"
    ["name"] =>  "ddd"
  }
  [4] => array(3) {
    ["id"]   =>  "25"
    ["pid"]  =>  "23"
    ["name"] =>  "eee"
  }
  [5] => array(3) {
    ["id"]   =>  "26"
    ["pid"]  =>  "22"
    ["name"] =>  "fff"
  }
}
</code>

重新排列为

<code>array(3) {
  [0] => array(3) {
    ["id"]   =>  "21"
    ["pid"]  =>  "0"
    ["name"] =>  "aaa"
  }
  [1] => array(4) {
    ["id"]   =>  "22"
    ["pid"]  =>  "0"
    ["name"] =>  "bbb"
    ["child"]=>  array(1) {
            [0] => array(3) {
                ["id"]   =>  "26"
                ["pid"]  =>  "22"
                ["name"] =>  "fff"
            }
    }
  }
  [2] => array(4) {
    ["id"]   =>  "23"
    ["pid"]  =>  "0"
    ["name"] =>  "ccc"    
    ["child"]=>  array(2) {
             [0] => array(3) {
                ["id"]   =>  "24"
                ["pid"]  =>  "23"
                ["name"] =>  "ddd"
            }
            [1] => array(3) {
                ["id"]   =>  "25"
                ["pid"]  =>  "23"
                ["name"] =>  "eee"
            }
    }
  }
}
</code>

涉及层级关系只有两层。

回复内容:

从数据表里取得一组二维数组,每个元素有键为 id 和 pid 的值,在不使用递归的情况下,如何按照其 pid 的值将元素移入到相应 id 元素中成为其子元素?

<code>array(6) {
  [0] => array(3) {
    ["id"]   =>  "21"
    ["pid"]  =>  "0"
    ["name"] =>  "aaa"
  }
  [1] => array(3) {
    ["id"]   =>  "22"
    ["pid"]  =>  "0"
    ["name"] =>  "bbb"
  }
  [2] => array(3) {
    ["id"]   =>  "23"
    ["pid"]  =>  "0"
    ["name"] =>  "ccc"
  }
  [3] => array(3) {
    ["id"]   =>  "24"
    ["pid"]  =>  "23"
    ["name"] =>  "ddd"
  }
  [4] => array(3) {
    ["id"]   =>  "25"
    ["pid"]  =>  "23"
    ["name"] =>  "eee"
  }
  [5] => array(3) {
    ["id"]   =>  "26"
    ["pid"]  =>  "22"
    ["name"] =>  "fff"
  }
}
</code>

重新排列为

<code>array(3) {
  [0] => array(3) {
    ["id"]   =>  "21"
    ["pid"]  =>  "0"
    ["name"] =>  "aaa"
  }
  [1] => array(4) {
    ["id"]   =>  "22"
    ["pid"]  =>  "0"
    ["name"] =>  "bbb"
    ["child"]=>  array(1) {
            [0] => array(3) {
                ["id"]   =>  "26"
                ["pid"]  =>  "22"
                ["name"] =>  "fff"
            }
    }
  }
  [2] => array(4) {
    ["id"]   =>  "23"
    ["pid"]  =>  "0"
    ["name"] =>  "ccc"    
    ["child"]=>  array(2) {
             [0] => array(3) {
                ["id"]   =>  "24"
                ["pid"]  =>  "23"
                ["name"] =>  "ddd"
            }
            [1] => array(3) {
                ["id"]   =>  "25"
                ["pid"]  =>  "23"
                ["name"] =>  "eee"
            }
    }
  }
}
</code>

涉及层级关系只有两层。

我想学算法的时候应该有讲过如何把递归改成循环实现。
一般递归都可以用队列+循环来实现,你先想想,空了来写程序。

你这个本来就是该循环实现的,哪里需要递归啊……

没得PHP的环境,用JS给你写个

要是看不懂 JS,C# 和 Java 看得懂不?PHP丢太久了,语法都忘了

<code>javascript</code><code>var data = [{
    "id": "21",
    "pid": "0",
    "name": "aaa"
}, {
    "id": "22",
    "pid": "0",
    "name": "bbb"
}, {
    "id": "23",
    "pid": "0",
    "name": "ccc"
}, {
    "id": "24",
    "pid": "23",
    "name": "ddd"
}, {
    "id": "25",
    "pid": "23",
    "name": "eee"
}, {
    "id": "26",
    "pid": "22",
    "name": "fff"
}];


var map = {}
var root = []
data.forEach(function(item) {
    map[item.id] = item;
    var parent = map[item.pid];
    if (parent) {
        parent.child = parent.child || [];
        parent.child.push(item);
    } else {
        root.push(item);
    }
});

console.log(JSON.stringify(root, null, 4));
</code>

输出

<code>[
    {
        "id": "21",
        "pid": "0",
        "name": "aaa"
    },
    {
        "id": "22",
        "pid": "0",
        "name": "bbb",
        "child": [
            {
                "id": "26",
                "pid": "22",
                "name": "fff"
            }
        ]
    },
    {
        "id": "23",
        "pid": "0",
        "name": "ccc",
        "child": [
            {
                "id": "24",
                "pid": "23",
                "name": "ddd"
            },
            {
                "id": "25",
                "pid": "23",
                "name": "eee"
            }
        ]
    }
]
</code>

非常感谢诸位的解答。看了你们的答案还在消化。基础不扎实还要多学习。
自己参考了一下隔壁问题。实现的代码如下:

<code>$arr = array(
    array('id'=>21, 'pid'=>0, 'name'=>'aaa'),
    array('id'=>22, 'pid'=>0, 'name'=>'bbb'),
    array('id'=>23, 'pid'=>0, 'name'=>'ccc'),
    array('id'=>24, 'pid'=>23, 'name'=>'ddd'),
    array('id'=>25, 'pid'=>23, 'name'=>'eee'),
    array('id'=>26, 'pid'=>22, 'name'=>'fff'),
    );

$temp=[];
foreach ($arr as $item)
{
    list($id,$pid,$name) = array_values($item); // 取出数组的值并分别生成变量

    if(array_key_exists($pid, $temp)) 
    // 检查临时数组$temp中是否存在键名与$pid的值相同的键
    {
        $temp[$pid]['child'][]=array('id'=>$id,'pid'=>$pid,'name'=>$name);
        // 如果存在则新增数组至临时数组中键名为 $pid 的子元素 child 内
    }else
        $temp[$id]=array('id'=>$id,'pid'=>$pid,'name'=>$name);
        // 如果不存在则新增数组至临时数组中并设定键名为 $id
}

$array = array_values($temp);
// 将临时数组中以 $id 为键名的键修改为数字索引

echo "<pre class="brush:php;toolbar:false">";
print_r($array);

取值生成变量步骤有点多余,foreach 部分更新如下:

<code>foreach ($arr as $item)
{
    if (array_key_exists($item['pid'], $temp))
    {       
        $temp[$item['pid']]['child'][]=$item;
    }else
        $temp[$item['id']]=$item;
}
</code>

先算出每个数组的顶级pid,然后再排序下。

<code><?php // 原本的数组, 偷个懒用JSON还原之
$arr = json_decode('[{
    "id": "21",
    "pid": "0",
    "name": "aaa"
}, {
    "id": "22",
    "pid": "0",
    "name": "bbb"
}, {
    "id": "23",
    "pid": "0",
    "name": "ccc"
}, {
    "id": "24",
    "pid": "23",
    "name": "ddd"
}, {
    "id": "25",
    "pid": "23",
    "name": "eee"
}, {
    "id": "26",
    "pid": "22",
    "name": "fff"
}]',TRUE);

$newArr = $rtnArr = array();
$current = array_shift($arr);
while($current){
    if($current['pid']){
        if(array_key_exists($current['pid'],$newArr)){
            $newArr[$current['pid']]['child'][]= $current;
        }else{
            $newArr[$current['pid']] = array('id'=>$current['pid'],'child'=>array());
        }
    }else{
        if(array_key_exists($current['id'],$newArr)){
            array_merge($newArr[$current['id']],$current);
        }else{
            $newArr[$current['id']] = $current;
        }
    }
    $current = array_shift($arr);
}

// 更新数组和子数组的排序
ksort($newArr);
foreach($newArr as $arr){
    if(array_key_exists('child',$arr)){
        usort($arr['child'],function($a,$b){
            return $a['id'] > $b['id'] ? 1 : -1;
        });
    }
    array_push($rtnArr,$arr);
}

// 打印
print_r($rtnArr);

?>
</code>
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn