2

given a nested array of arbitrary depth like this:

$array = array(
            1400=> 
                array(7300=>
                        array(
                            7301=> array(),
                            7302=> array(),
                            7305=> array(
                                7306=>array()
                            ),
                        ),
                    7314=>array()
                ),
            );

how would one get the hierarchy of keys for any key.

for example:

getkeys(7305);

should return 1400,7300,7305 in that order

or

getkeys(7314);

should return 1400,7314

all array keys are unique values

6
  • array_walk with a secondary array to store references to. Commented Nov 30, 2015 at 16:18
  • @MiDri if can please make an answer. not sure what you mean. Commented Nov 30, 2015 at 16:20
  • 1
    Read array_walk documentation should be straight forward after that. Commented Nov 30, 2015 at 16:21
  • @MiDri read it. not at all straight forward to me Commented Nov 30, 2015 at 16:24
  • 2
    It's not a straight forward thing to do, you need to write a recursive function that array_walk can call to comb the array of arrays. Commented Nov 30, 2015 at 16:30

3 Answers 3

2

Using RecursiveIteratorIterator

$array = array(
  1400 => array(
    7300 => array(
      7301=> array(),
      7302 => array(),
      7305 => array(
        7306=>array()
      ),
    ),
    7314=>array()
  ),
);

function getKeys($key, $array) {
  $found_path = [];
  $ritit = new RecursiveIteratorIterator(new RecursiveArrayIterator($array), RecursiveIteratorIterator::SELF_FIRST);

  foreach ($ritit as $leafValue) {

    $path = array();
    foreach (range(0, $ritit->getDepth()) as $depth) {
      $path[] = $ritit->getSubIterator($depth)->key();
    }

    if (end($path) == $key) {
      $found_path = $path;
      break;
    }
  }

  return $found_path;
}

print_r(getKeys(7305, $array));
// Array
// (
//     [0] => 1400
//     [1] => 7300
//     [2] => 7305
// )
Sign up to request clarification or add additional context in comments.

Comments

1

This is very interesting problem you have so I tried to make a function that will echo your keys. If this is not good enough pls let me know I can improve code. Thanks.

<?php

$a = array(
            1400=> 
                array(7300=>
                        array(
                            7301=> array(),
                            7302=> array(),
                            7305=> array(
                                7306=>array()
                            ),
                        ),
                    7314=>array()
                ),
            );

$mykey = 7306;
$level = 0;
$result = array();
$resultarray = test($a,$mykey,$level,$result);

function test($array,$mykey,$level,$result){
    $level++;
    foreach($array as $key => $element){
        if($key == $mykey){
            echo 'found';
            print_r($result);
            exit;
        } else if(is_array($element)){
            $result[$level] = $key;
            $result1 = test($element,$mykey,$level,$result);
        }
    }
}

Comments

1

The idea is to check current array branch, and if the needle key isn't found, then iterate current items and check their array child nodes by recursive function calls. Before each step down we push a current key to stack, and pop the stack if the function does not found a needle key in whole branch. So if the key found, the function returns true by the chain, preserving successful keys in the stack.

function branchTraversing(& $branch, & $key_stack, $needle_key) {
  $found = false;
  if (!array_key_exists($needle_key, $branch)) {
    reset($branch);
    while (!$found && (list($key, $next_branch) = each($branch))) {
      if (is_array($next_branch)) {
        array_push($key_stack, $key);
        $found = branchTraversing($next_branch, $key_stack, $needle_key);
        if (!$found) {
          array_pop($key_stack);
        }
      }
    }
  } else {
    array_push($key_stack, $needle_key);
    $found = true;
  }

  return $found;
}

function getPath(& $array, $needle_key) {
  $path = [];
  branchTraversing($array, $path, $needle_key);
  return $path;
}

$test_keys = [1400, 7300, 7302, 7306, 7314, 666];

foreach ($test_keys as $search_key) {
  echo '<p>' . $search_key . ' => [ '
  . implode(', ', getPath($array, $search_key)) . ' ]</p>';
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.