3v4l.org

run code in 300+ PHP versions simultaneously
<?php // https://axenov.dev/php-trees-without-recursion/ // функция построения дерева без рекурсии function tree( array $flat_list, string $fk = 'hid', string $pk = 'id', ): array { $tree = []; foreach ($flat_list as &$node) { $references[$node[$pk]] = &$node; if (empty($node[$fk])) { $tree[$node[$pk]] = &$node; } else { $references[$node[$fk]]['children'][] = &$node; } } return $tree; } //============================================ // Кейс 1. Допустим, массив неассоциирован //============================================ // пример вспомогательной фукции для ассоциации массива function key_by_field(array $flat_list, string $pk = 'id'): array { $result = []; foreach ($flat_list as $element) { $result[$element[$pk]] = $element; } return $result; } // исходные данные $data = <<<JSON [ { "id": 1, "hid": null, "title": "Root" }, { "id": 2, "hid": 1, "title": "Branch 1" }, { "id": 3, "hid": 2, "title": "Leaf 1.1" }, { "id": 5, "hid": 1, "title": "Branch 2" }, { "id": 6, "hid": 5, "title": "Leaf 2.1" }, { "id": 4, "hid": 2, "title": "Leaf 1.2" }, { "id": 7, "hid": 5, "title": "Leaf 2.2" } ] JSON; $json = json_decode($data, JSON_OBJECT_AS_ARRAY | JSON_THROW_ON_ERROR); $json = key_by_field($json); // формирование нового списка элементов print_r(tree($json)); //============================================ // Кейс 2. Допустим, массив ассоциирован //============================================ $data2 = <<<JSON { "1": { "id": 1, "hid": null, "title": "Root" }, "3": { "id": 2, "hid": 2, "title": "Leaf 1.1" }, "2": { "id": 3, "hid": 1, "title": "Branch 1" }, "5": { "id": 5, "hid": 1, "title": "Branch 2" }, "6": { "id": 6, "hid": 5, "title": "Leaf 2.1" }, "4": { "id": 4, "hid": 2, "title": "Leaf 1.2" }, "7": { "id": 7, "hid": 5, "title": "Leaf 2.2" } } JSON; $json2 = json_decode($data2, JSON_OBJECT_AS_ARRAY | JSON_THROW_ON_ERROR); // формирование нового списка элементов print_r(tree($json2));
Output for 8.0.1 - 8.0.30, 8.1.0 - 8.1.28, 8.2.0 - 8.2.19, 8.3.0 - 8.3.7
Array ( [1] => Array ( [id] => 1 [hid] => [title] => Root [children] => Array ( [0] => Array ( [id] => 2 [hid] => 1 [title] => Branch 1 [children] => Array ( [0] => Array ( [id] => 3 [hid] => 2 [title] => Leaf 1.1 ) [1] => Array ( [id] => 4 [hid] => 2 [title] => Leaf 1.2 ) ) ) [1] => Array ( [id] => 5 [hid] => 1 [title] => Branch 2 [children] => Array ( [0] => Array ( [id] => 6 [hid] => 5 [title] => Leaf 2.1 ) [1] => Array ( [id] => 7 [hid] => 5 [title] => Leaf 2.2 ) ) ) ) ) ) Array ( [1] => Array ( [id] => 1 [hid] => [title] => Root [children] => Array ( [0] => Array ( [id] => 3 [hid] => 1 [title] => Branch 1 ) [1] => Array ( [id] => 5 [hid] => 1 [title] => Branch 2 [children] => Array ( [0] => Array ( [id] => 6 [hid] => 5 [title] => Leaf 2.1 ) [1] => Array ( [id] => 7 [hid] => 5 [title] => Leaf 2.2 ) ) ) ) ) )

preferences:
136.92 ms | 410 KiB | 91 Q