У меня есть одномерный массив с stdclasses внутри, эти объекты имеют имя и атрибут "abh". теперь я хочу получить древовидный вид, такой как многомерный массив. Допустим, мой массив выглядит так:
$ar = array(
(object)array("name" => "Test1","otherstuff"=>array(),"abh"=>""),
(object)array("name" => "Test2","otherstuff"=>array(),"abh"=>"Test1"),
(object)array("name" => "Test3","otherstuff"=>array(),"abh"=>"Test1"),
(object)array("name" => "Test4","otherstuff"=>array(),"abh"=>"Test1"),
(object)array("name" => "Test5","otherstuff"=>array(),"abh"=>"Test1"),
(object)array("name" => "Test6","otherstuff"=>array(),"abh"=>"Test5"),
(object)array("name" => "Test7","otherstuff"=>array(),"abh"=>"Test5"),
(object)array("name" => "Test8","otherstuff"=>array(),"abh"=>array("Test5","Test7")),
(object)array("name" => "Test9","otherstuff"=>array(),"abh"=>"Test8"),
(object)array("name" => "Test10","otherstuff"=>array(),"abh"=>"Test6"),
(object)array("name" => "Test11","otherstuff"=>array(),"abh"=>"Test9"),
);
имена данных из функций, вызываемых ранее, а не из базы данных. Результат выглядит примерно так:
Array
(
[0] => stdClass Object
(
[name] => Test1
[otherstuff] => Array
(
)
[abh] =>
)
[1] => stdClass Object
(
[name] => Test2
[otherstuff] => Array
(
)
[abh] => Test1
)
[...]
)
поэтому теперь я хочу, чтобы этот массив сортировался по атрибуту "abh". первый, где "abh" пуст, его корень, все остальные станут его дочерьми. поэтому функция должна добавить атрибут "childs" к основному IF, если у него есть дочерние элементы. Но теперь этот тип является особым, потому что "abh" может быть массивом и переходить к n-родителям. В моем примере выше Test8 должен быть дочерним элементом Test5 и Test7 (клон).
Я попытался справиться с этим с помощью рекурсивной функции и циклов в foreach. Там он проверяет abh элемента againts, который существует, но не работает. array_filter() doenst делает это, как я хочу.
поэтому, я хочу этот результат:
Array
(
[Test1] => stdClass Object
(
[name] => Test1
[otherstuff] => Array()
[abh] =>
[childs] => Array
(
[Test2] => stdClass Object
[...] and so on
)
)
)
любые идеи об этом? Я также не знаю, сколько "уровней" будет иметь возвращенный массив, т.е. сколько входных объектов и "abh" -assignes существует. Секунды состоят в том, что массив "abh" может иметь до 10 "родителей".
Спасибо за любую помощь!
как запросить мой нерабочий прототип для этого "сортировщика",
function checkABH(&$return,&$ar,$deph) {
// clone all with array-abh
$count = count($ar);
for($x=0;$x<$count;$x++) {#$ar as$key=>$val) {
if(is_array($ar[$x]->abh)) {
$clone = $ar[$x];
foreach($ar[$x]->abh as$abh) {
#echo "<br>$x @@ $abh";
$clone->abh = $abh;
$ar[] = $clone;
#echo '<pre>'.print_r($clone,true).'</pre>';
}
// delete array-abh-element
unset($ar[$x]);
}
}
echo '<pre>'.print_r($ar,true).'</pre>';
echo '</div>';
echo '<div style="float:left;width:auto;margin:0px 10px;"><h3>Result:</h3>';
// pass to sorter
checkABH_a($return,$ar,$deph);
}
function checkABH_a(&$return,&$ar,$deph) {
$test_abhs = array();
foreach($ar as$key=>$val) {
$val->childs = array();
if(isset($return[$deph])&&isset($return[$deph]->name)&&$val->abh==$return[$deph]->name) {
$return[$deph]->childs[] = $val;
unset($ar[$key]);
} elseif($val->abh==$deph) {
$return[$val->abh] = $val;
unset($ar[$key]);
} else {
$test_abhs[] = $val->abh;
}
}
if(count($test_abhs)>0) {
$test_abhs = array_unique($test_abhs);
#echo '<pre>'.print_r($test_abhs,true).'</pre>';
foreach($test_abhs as$abh) {
checkABH_a($return,$ar,$abh);
}
}
}
echo '<div style="float:left;width:260px;border-right:1px solid #cccccc;margin:0px 10px;"><h3>Input</h3>';
echo '<pre>'.print_r($ar,true).'</pre>';
echo '</div>';
echo '<div style="float:left;width:260px;border-right:1px solid #cccccc;margin:0px 10px;"><h3>Cloned:</h3>';
$return = array();
checkABH($return,$ar,"");
echo'<pre>'.print_r($return,true).'</pre>';
echo '</div>';
Эти рекурсивные деревья не становятся более легкими, что добавляет требование "множественного родителя";//Что бы это ни было, оно все еще выглядит интересным...
Я не буду документировать весь код здесь, поскольку я думаю, что уже достаточно прокомментировал это.
Заметки:
Рабочая версия кода на Viper-7.com с использованием PHP 5.3.18
Любые вопросы о коде, а затем отправьте комментарии, и я попробую ответить им.
<?php // https://stackoverflow.com/questions/27360813/php-convert-array-to-multidimensional-array-by-parent-id
$ar = array(
(object) array("name" => "Test1", "otherstuff"=>array('parent is Test1'), "abh"=>""),
(object) array("name" => "Test2", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"),
(object) array("name" => "Test3", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"),
(object) array("name" => "Test4", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"),
(object) array("name" => "Test5", "otherstuff"=>array('parent is Test1'), "abh"=>"Test1"),
(object) array("name" => "Test6", "otherstuff"=>array('parent is Test5'), "abh"=>"Test5"),
(object) array("name" => "Test7", "otherstuff"=>array('parent is Test5'), "abh"=>"Test5"),
(object) array("name" => "Test8", "otherstuff"=>array('parent is Test5 AND Test7'), "abh"=>array("Test5", "Test7")),
(object) array("name" => "Test9", "otherstuff"=>array('parent is Test8'), "abh"=>"Test8"),
(object) array("name" => "Test10", "otherstuff"=>array('parent is Test6'), "abh"=>"Test6"),
(object) array("name" => "Test11", "otherstuff"=>array('parent is Test9'), "abh"=>"Test9"),
);
/*
* The requirement is that for any child then the parent must be in the tree already.
*/
// Convert those parent with 'arrays of parents' into individual entries as it will make the insert
// easier to understand.
// i will also convert all the input into a 'TreeNode' class while i am doing this pass down the input.
// i can add some methods later if i wish.
// i will also get the root of the tree while i am doing this...
$rootNode = new TreeNode(array_shift($ar));
$treeNodeList = array();
foreach($ar as $node) {
if (is_array($node->abh)) { // generate duplicate nodes
foreach($node->abh as $parentName) {
$node->abh = $parentName; // make it an ordinary node
$treeNodeList[] = new TreeNode($node);
}
continue;
}
$treeNodeList[] = new TreeNode($node);
}
// var_dump($ar, $rootNode, $treeNodeList);
// Ok, we now have a node list in the appropriate order - let us build the tree
/**
* This is a 'multiway' tree .i.e. there can be any number of 'child' nodes
* for any parent
* Usual rules:
* o The parent MUST be in the tree already.
* o Children are added, by searching from the root of the tree, in this version
*
*/
// the output will be here
$theTree = array($rootNode->name => $rootNode);
foreach ($treeNodeList as $childNode) { // add it
$inserted = insertNode($rootNode, $childNode);
if (!$inserted) {
var_dump('Unable to insert:', $childNode, ' in tree:', $rootNode);
die('i am here: '. __FILE__.__LINE__);
}
}
// show the tree
echo '<pre>';
print_r($theTree);
echo '</pre>';
exit;
// --------- end of processing -------------
/**
* Insert the node in the tree
*
* @param TreeNode $parent
* @param TreeNode $newChild
*/
function insertNode(TreeNode &$parent, TreeNode $newChild) {
if ($newChild->abh === $parent->name) { // add it to the current parent
$parent->children[$newChild->name] = $newChild; // add child
return true;
}
// check the children
foreach($parent->children as $newParent) {
if (insertNode($newParent, $newChild)) {
return true;
}
}
return false; // unable to insert child in the tree
}
// -----------------------------------------------------------------------
/**
* treeNode: (Data and Relationships)
* nodeId: 'name'
* nodeData: 'otherstuff'
* nodeParentList: 'abh' - may be a list of parents.
* Note: In this version of the code: All the parents
* MUST be in the tree already.
* children: array of treeNode - recursive structure
*/
// i will make the properties all public to make it easier to debug.
class TreeNode {
public $name = '';
public $otherstuff = array();
public $abh = '';
public $children = array(); // list of child nodes
public function __construct(stdClass $node)
{
$this->name = $node->name;
$this->otherstuff = $node->otherstuff;
$this->abh = $node->abh;
}
} // class end --------------------------