Get path from adjacency list data

404 views Asked by At

I have an array (data from adjacency table) and it looks like:

Array
(
    [0] => Array
        (
            [id] => 1
            [name] => Anniversary
            [parent] => 0
        )

    [1] => Array
        (
            [id] => 12
            [name] => New arrives
            [parent] => 1
        )

    [2] => Array
        (
            [id] => 13
            [name] => Discount
            [parent] => 12
        )

    [3] => Array
        (
            [id] => 6
            [name] => Birthday
            [parent] => 0
        )
)

And I'm looking for the way to retrieve my path by ID;

For example: getPath(13): Anniversary->New arrives->Discount;
For example: getPath(12): Anniversary->New arrives;
For example: getPath(1): Anniversary;
For example: getPath(6): Birthday;

How can I do this? Thanks!

3

There are 3 answers

5
Narendrasingh Sisodia On BEST ANSWER
function getpath($id, $arr, $level = 0) {
    $result = array();
    foreach($arr as $key => $value){
        if($id == $value['id']){
            $result[] = $value['name'];
            $id = $value['parent'];
            if($id != 0){
              $result = array_merge($result, getpath($id, $arr, $level+1));
            }else{
                break;
            }
        }
    }
    return $level ? $result : implode('->',array_reverse($result));
}
echo getpath(13,$arr);
0
viral On

Consider this array,

$input = [
    ['id'=>1, 'name'=>'Anniversary', 'parent'=>0],
    ['id'=>12, 'name'=>'New arrives', 'parent'=>1],
    ['id'=>13, 'name'=>'Discount', 'parent'=>12],
    ['id'=>6, 'name'=>'Birthday', 'parent'=>0]
];

and this function,

function path($element_id, $input, $ids = [])
{
    if(!$ids) // for performance, make this once and pass it around
    {   
        $ids = array_column($input, 'id'); // array containing only 'id's of $input
    }   

    $current_key = array_search($element_id, $ids); // search for $input variable's current key

    unset($ids[$current_key]); // unsetting used keys to make above array search faster next time

    $current_element = $input[$current_key]; // get current element as array from $input

    $names[] = $current_element['name']; // create an array containing current element

    if($current_element['parent'] != 0) // check if current element have parent
    {   
        $names[] = path($current_element['parent'], $input, $ids); // call this function, let it return string, append it to $names
    }   

    return implode(' ⟶ ', array_reverse($names)); // make final return, seprate by ⟶
}

Reading echo path(13, $input); will return

Anniversary ⟶ New arrives ⟶ Discount

Here is minified version of the same function

function path($a,$b,$c=[]){if(!$c){$c=array_column($b,'id');}$d=array_search($a,$c);unset($c[$d]);$e=$b[$d];$f[]=$e['name'];if($e['parent']!=0){$f[]=path($e['parent'],$b,$c);}return implode(' ⟶ ',array_reverse($f));}

Thanks to code reviewers Loufylouf and Quill

1
splash58 On
$find = 13;
$path = array();

function FindById ($arr, $find) {
  $k = null;

  foreach($arr as $key => $item) 
    if ($item['id'] == $find) 
      { $k = $key; break; }
  return $k;
}

if ( false === ($k = FindById($arr, $find)))  die("not found");

while (true) {
   array_unshift($path, $arr[$k]['name']);
   if( !  $arr[$k]['parent']) break;
   if(false === ($k = FindById($arr, $arr[$k]['parent']))) die("illegal structure");

}  

echo implode('->', $path);