Ответ 1
Хотя @wizards answer работал, я чувствовал, что хочу сделать версию с более четким кодом. Ниже версия возвращает объект со связанными и неизолированными элементами, и я считаю, что это очень ясно, как это работает.
Причина, по которой я хочу работать таким образом, - это продлить ее для будущих вопросов. Например, "Сколько раз связан элемент" или "У кого больше ссылок". Он также может быть легко адаптирован для ответа на эти вопросы.
Другим преимуществом является то, что он использует как можно более ограниченные циклы, что может ускорить процесс, когда размер увеличивается.
<?php
error_reporting(E_ALL);
$obj_array = [] ;
$obj = new stdClass;
$obj->id = 1;
$obj->name = "Apple";
$obj->link = array(14, 5);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 3;
$obj->name = "Carrot";
$obj->link = array(1, 14, 3);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 4;
$obj->name = "Dill";
$obj->link = array(1, 5);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 5;
$obj->name = "Egg";
$obj->link = array(6);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 6;
$obj->name = "Fred";
$obj->link = array(7);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 7;
$obj->name = "Goat";
$obj->link = array(7, 8);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 8;
$obj->name = "Harry";
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 9;
$obj->name = "Igloo";
$obj->link = array(14, 5);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 10;
$obj->name = "Jason";
$obj->link = array(1, 5, 8);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 11;
$obj->name = "Klaus";
$obj->link = array(1, 5, 10);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 14;
$obj->name = "Banana";
$obj->link = array(3);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 15;
$obj->name = "Oyster1";
$obj->link = array(16);
$obj_array[] = $obj;
$obj = new stdClass;
$obj->id = 16;
$obj->name = "Oyster2";
$obj->link = array(15);
$obj_array[] = $obj;
/*
* CALL
*/
$parser = new ObjectLinker($obj_array, 1);
//dump found
//decode/encode to only show public values
print_r(json_decode(json_encode($parser)));
/*
* ACTUAL CODE
*/
class ObjectLinker
{
private $_array;
private $_start;
public $LinkedElements = array();
public $UnLinkedElements = array();
final public function __construct($ar, $start)
{
$this->_array = $ar;
$this->_start = $start;
$this->getElementsArray();
$this->findLinked($this->_start);
}
final private function getElementsArray()
{
//since each Id is unique, i'm using the ID as the key in the array. this will allow faster access
//Ofcourse it would be better if you would create the array like this in the first place, then you can skip this step
foreach($this->_array as $obj) {
if (!is_null($obj) && property_exists($obj, 'id')) {
//I add everything to the unlinked elements. We will remove the linked once, to have once less loop
$this->UnLinkedElements[$obj->id] = $obj;
}
}
}
final private function findLinked($id)
{
//If the key is not in the array, it already loaded
if (!array_key_exists($id, $this->UnLinkedElements)) {
return;
}
//get obj
//Because of the getElementsArray() step, I'm already sure the object exists.
//If you change the input array, you might want to check for invalid obj
$obj = $this->UnLinkedElements[$id];
//add to linked
$this->LinkedElements[$id] = $obj;
//remove from unlinked
unset($this->UnLinkedElements[$id]);
//no links
if (!property_exists($obj, 'link')) {
return;
}
$links = $obj->link;
//Invalid links
if (!is_array($links)) {
return;
}
//check links
foreach($links as $link) {
$this->findLinked($link);
}
}
}
?>
Вывод:
stdClass Object
(
[LinkedElements] => stdClass Object
(
[1] => stdClass Object
(
[id] => 1
[name] => Apple
[link] => Array
(
[0] => 14
[1] => 5
)
)
[14] => stdClass Object
(
[id] => 14
[name] => Banana
[link] => Array
(
[0] => 3
)
)
[3] => stdClass Object
(
[id] => 3
[name] => Carrot
[link] => Array
(
[0] => 1
[1] => 14
[2] => 3
)
)
[5] => stdClass Object
(
[id] => 5
[name] => Egg
[link] => Array
(
[0] => 6
)
)
[6] => stdClass Object
(
[id] => 6
[name] => Fred
[link] => Array
(
[0] => 7
)
)
[7] => stdClass Object
(
[id] => 7
[name] => Goat
[link] => Array
(
[0] => 7
[1] => 8
)
)
[8] => stdClass Object
(
[id] => 8
[name] => Harry
)
)
[UnLinkedElements] => stdClass Object
(
[4] => stdClass Object
(
[id] => 4
[name] => Dill
[link] => Array
(
[0] => 1
[1] => 5
)
)
[9] => stdClass Object
(
[id] => 9
[name] => Igloo
[link] => Array
(
[0] => 14
[1] => 5
)
)
[10] => stdClass Object
(
[id] => 10
[name] => Jason
[link] => Array
(
[0] => 1
[1] => 5
[2] => 8
)
)
[11] => stdClass Object
(
[id] => 11
[name] => Klaus
[link] => Array
(
[0] => 1
[1] => 5
[2] => 10
)
)
[15] => stdClass Object
(
[id] => 15
[name] => Oyster1
[link] => Array
(
[0] => 16
)
)
[16] => stdClass Object
(
[id] => 16
[name] => Oyster2
[link] => Array
(
[0] => 15
)
)
)
)