создать дерево массивов из списка массивов
78421 просмотра
8 ответа
у меня есть такой список:
array(
array(id=>100, parentid=>0, name=>'a'),
array(id=>101, parentid=>100, name=>'a'),
array(id=>102, parentid=>101, name=>'a'),
array(id=>103, parentid=>101, name=>'a'),
)
но намного больше, поэтому мне нужен эффективный способ превратить это в древовидную структуру, подобную этой:
array(
id=>100, parentid=>0, name=>'a', children=>array(
id=>101, parentid=>100, name=>'a', children=>array(
id=>102, parentid=>101, name=>'a',
id=>103, parentid=>101, name=>'a',
)
)
)
я не могу использовать такие вещи, как вложенные множества или подобные вещи, потому что я могу добавлять левые и правые значения в мою базу данных. есть идеи?
Автор: Thunderstriker Источник Размещён: 12.11.2019 09:06Ответы (8)
55 плюса
Ок, вот как я это решил:
$arr = array(
array('id'=>100, 'parentid'=>0, 'name'=>'a'),
array('id'=>101, 'parentid'=>100, 'name'=>'a'),
array('id'=>102, 'parentid'=>101, 'name'=>'a'),
array('id'=>103, 'parentid'=>101, 'name'=>'a'),
);
$new = array();
foreach ($arr as $a){
$new[$a['parentid']][] = $a;
}
$tree = createTree($new, array($arr[0]));
print_r($tree);
function createTree(&$list, $parent){
$tree = array();
foreach ($parent as $k=>$l){
if(isset($list[$l['id']])){
$l['children'] = createTree($list, $list[$l['id']]);
}
$tree[] = $l;
}
return $tree;
}
Автор: Thunderstriker
Размещён: 16.11.2010 05:10
40 плюса
Небольшое исправление, если вам нужно более 1 элемента parentid [0] :)
$arr = array(
array('id'=>100, 'parentid'=>0, 'name'=>'a'),
array('id'=>101, 'parentid'=>100, 'name'=>'a'),
array('id'=>102, 'parentid'=>101, 'name'=>'a'),
array('id'=>103, 'parentid'=>101, 'name'=>'a'),
);
$new = array();
foreach ($arr as $a){
$new[$a['parentid']][] = $a;
}
$tree = createTree($new, $new[0]); // changed
print_r($tree);
function createTree(&$list, $parent){
$tree = array();
foreach ($parent as $k=>$l){
if(isset($list[$l['id']])){
$l['children'] = createTree($list, $list[$l['id']]);
}
$tree[] = $l;
}
return $tree;
}
Автор: arthur
Размещён: 26.04.2012 11:20
15 плюса
Еще одна переделка варианта Thunderstriker - вся логика в одной функции:
/**
* @param $flatList - a flat list of tree nodes; a node is an array with keys: id, parentID, name.
*/
function buildTree(array $flatList)
{
$grouped = [];
foreach ($flatList as $node){
$grouped[$node['parentID']][] = $node;
}
$fnBuilder = function($siblings) use (&$fnBuilder, $grouped, $idKey) {
foreach ($siblings as $k => $sibling) {
$id = $sibling['id'];
if(isset($grouped[$id])) {
$sibling['children'] = $fnBuilder($grouped[$id]);
}
$siblings[$k] = $sibling;
}
return $siblings;
};
$tree = $fnBuilder($grouped[0]);
return $tree;
}
// Example:
$flat = [
['id' => 100, 'parentID' => 0, 'name' => 'root'],
['id' => 101, 'parentID' => 100, 'name' => 'ch-1'],
['id' => 102, 'parentID' => 101, 'name' => 'ch-1-1'],
['id' => 103, 'parentID' => 101, 'name' => 'ch-1-2'],
];
$tree = buildTree($flat, 'parentID', 'id');
echo json_encode($tree, JSON_PRETTY_PRINT);
Детская площадка: https://www.tehplayground.com/xOqMQd11W96XljZV
Автор: Vasily Размещён: 08.12.2014 02:539 плюса
Вот моя адаптация от переделки Артура :
/* Recursive branch extrusion */
function createBranch(&$parents, $children) {
$tree = array();
foreach ($children as $child) {
if (isset($parents[$child['id']])) {
$child['children'] =
$this->createBranch($parents, $parents[$child['id']]);
}
$tree[] = $child;
}
return $tree;
}
/* Initialization */
function createTree($flat, $root = 0) {
$parents = array();
foreach ($flat as $a) {
$parents[$a['parent']][] = $a;
}
return $this->createBranch($parents, $parents[$root]);
}
Использование:
$tree = createTree($flat);
Автор: Pierre de LESPINAY
Размещён: 25.02.2014 04:44
6 плюса
Я создал необычную («основанную на времени», а не рекурсивную), но многомерную функцию сортировки, которая обходит массив, пока не останется сирот. Здесь функция:
function treeze( &$a, $parent_key, $children_key )
{
$orphans = true; $i;
while( $orphans )
{
$orphans = false;
foreach( $a as $k=>$v )
{
// is there $a[$k] sons?
$sons = false;
foreach( $a as $x=>$y )
if( isset($y[$parent_key]) and $y[$parent_key]!=false and $y[$parent_key]==$k )
{
$sons=true;
$orphans=true;
break;
}
// $a[$k] is a son, without children, so i can move it
if( !$sons and isset($v[$parent_key]) and $v[$parent_key]!=false )
{
$a[$v[$parent_key]][$children_key][$k] = $v;
unset( $a[$k] );
}
}
}
}
Рекомендация: ключ каждого элемента массива должен быть идентификатором самого элемента. Пример:
$ARRAY = array(
1 => array( 'label' => "A" ),
2 => array( 'label' => "B" ),
3 => array( 'label' => "C" ),
4 => array( 'label' => "D" ),
5 => array( 'label' => "one", 'father' => '1' ),
6 => array( 'label' => "two", 'father' => '1' ),
7 => array( 'label' => "three", 'father' => '1' ),
8 => array( 'label' => "node 1", 'father' => '2' ),
9 => array( 'label' => "node 2", 'father' => '2' ),
10 => array( 'label' => "node 3", 'father' => '2' ),
11 => array( 'label' => "I", 'father' => '9' ),
12 => array( 'label' => "II", 'father' => '9' ),
13 => array( 'label' => "III", 'father' => '9' ),
14 => array( 'label' => "IV", 'father' => '9' ),
15 => array( 'label' => "V", 'father' => '9' ),
);
Использование: функции нужны $ a (массив), $ parent_key (имя столбца, в котором сохранен идентификатор отца), $ children_key (имя столбца, в который будут перемещаться дочерние элементы). Он ничего не возвращает (массив изменяется по ссылке). Пример:
treeze( $ARRAY, 'father', 'children' );
echo "<pre>"; print_r( $ARRAY );
Автор: Marco Panichi
Размещён: 26.04.2012 03:29
2 плюса
//if order by parentid, id
$arr = array(
array('id'=>100, 'parentid'=>0, 'name'=>'a'),
array('id'=>101, 'parentid'=>100, 'name'=>'a'),
array('id'=>102, 'parentid'=>101, 'name'=>'a'),
array('id'=>103, 'parentid'=>101, 'name'=>'a'),
);
$arr_tree = array();
$arr_tmp = array();
foreach ($arr as $item) {
$parentid = $item['parentid'];
$id = $item['id'];
if ($parentid == 0)
{
$arr_tree[$id] = $item;
$arr_tmp[$id] = &$arr_tree[$id];
}
else
{
if (!empty($arr_tmp[$parentid]))
{
$arr_tmp[$parentid]['children'][$id] = $item;
$arr_tmp[$id] = &$arr_tmp[$parentid]['children'][$id];
}
}
}
unset($arr_tmp);
echo '<pre>'; print_r($arr_tree); echo "</pre>";
Автор: Pham
Размещён: 20.05.2016 08:14
1 плюс
Один из способов сделать это - с помощью рекурсивной функции, которая сначала находит все нижние значения списка, добавляя их в новый массив. Затем для каждого нового идентификатора вы используете ту же функцию для этого идентификатора, беря возвращенный массив и помещая его в новый дочерний массив этого элемента. Наконец, вы возвращаете свой новый массив.
Я не буду делать всю работу за вас, но параметры функции будут выглядеть примерно так:
функция recursiveChildren ($ items_array, $ parent_id = 0)
По сути, он найдет все с родительским значением 0, затем для каждого из них он найдет все с этим идентификатором в качестве родителя, и для каждого из них ... и так далее.
Конечный результат должен быть тем, что вы ищете.
Автор: DampeS8N Размещён: 16.11.2010 04:161 плюс
Есть ли причина, по которой этот трехпроходный метод не сработает? Я не делал никаких тестов, чтобы сравнить скорость с некоторыми рекурсивными решениями, но это казалось более простым. Если ваш исходный массив уже связан с идентификаторами, являющимися ключом, то вы можете пропустить первый foreach()
.
function array_tree(&$array) {
$tree = array();
// Create an associative array with each key being the ID of the item
foreach($array as $k => &$v) {
$tree[$v['id']] = &$v;
}
// Loop over the array and add each child to their parent
foreach($tree as $k => &$v) {
if(!$v['parent']) {
continue;
}
$tree[$v['parent']]['children'][] = &$v;
}
// Loop over the array again and remove any items that don't have a parent of 0;
foreach($tree as $k => &$v) {
if(!$v['parent']) {
continue;
}
unset($tree[$k]);
}
return $tree;
}
Автор: psyon
Размещён: 04.11.2014 05:44
Вопросы из категории :
- php Как вы отлаживаете PHP-скрипты?
- php Заставьте XAMPP / Apache обслуживать файл вне htdocs
- php Как включить файлы PHP, которые требуют абсолютного пути?
- php Скрипт входа со скрытыми кнопками
- php How can I find unused functions in a PHP project
- arrays Как удалить дубликаты из массива C #?
- arrays Как определить размер моего массива в C?
- arrays Каков наилучший способ конвертировать массив в хеш в Ruby
- arrays Сравнение двухбайтовых массивов в .NET
- arrays Можно ли выполнять параллельные обходы в MATLAB так же, как в Python?
- recursion Find number of files with a specific extension, in all subdirectories
- recursion Что такое хвостовая рекурсия?
- recursion Рекурсия или итерация?
- recursion Путь от рекурсии к итерации
- recursion Рекурсивный список файлов в CLI Linux с указанием пути относительно текущего каталога
- tree Когда использовать Binary Space Partitioning, Quadtree, Octree?
- tree Как эффективно построить дерево из плоской конструкции?
- tree Алгоритм поиска избыточных ребер в графе или дереве
- tree Какова степень дерева? (Как в дереве ADT)
- tree Как проверить, имеет ли дерево идеальное совпадение по линейному времени?