5

Sorry for the terrible title, best I could think of at the time! Say I have a 'path' array like so;

array('this', 'is', 'the', 'path')

What would be the most effective method to end up with the array below?

array(
    'this' => array(
        'is' => array(
            'the' => array(
                'path' => array()
            )
        )
    )
)
1
  • Do you want to get a value, set a value or build such a structure by that path? Commented May 12, 2015 at 19:53

5 Answers 5

6

Just iterate over it with something like array_shift or array_pop:

$inarray = array('this', 'is', 'the', 'path',);
$tree = array();
while (count($inarray)) {
    $tree = array(array_pop($inarray) => $tree,);
}

Not tested, but that's the basic structure of it. Recursion also fits the task well. Alternatively, if you don't want to modify the initial array:

$inarray = array('this', 'is', 'the', 'path',);
$result = array();
foreach (array_reverse($inarray) as $key)
    $result = array($key => $result,);
Sign up to request clarification or add additional context in comments.

Comments

6

I use two similar functions to get and set values by their path within an array:

function array_get($arr, $path)
{
    if (!$path)
        return null;

    $segments = is_array($path) ? $path : explode('/', $path);
    $cur =& $arr;
    foreach ($segments as $segment) {
        if (!isset($cur[$segment]))
            return null;

        $cur = $cur[$segment];
    }

    return $cur;
}

function array_set(&$arr, $path, $value)
{
    if (!$path)
        return null;

    $segments = is_array($path) ? $path : explode('/', $path);
    $cur =& $arr;
    foreach ($segments as $segment) {
        if (!isset($cur[$segment]))
            $cur[$segment] = array();
        $cur =& $cur[$segment];
    }
    $cur = $value;
}

Then you use them like this:

$value = array_get($arr, 'this/is/the/path');
$value = array_get($arr, array('this', 'is', 'the', 'path'));
array_set($arr, 'here/is/another/path', 23);

Comments

1
function buildArrayFromPath( $path ) {
  $out = array();
  while( $pop = array_pop($path) ) $out = array($pop => $out);
  return $out;
}

Comments

1

One recursive solution:

function find_in_array(&$array, &$path, $_i=0) {
  // sanity check
  if ( !(is_array($array) && is_array($path)) ) return false;
  $c = count($path); if ($_i >= $c) return false;

  $k = $path[$_i];
  if (array_key_exists($k, $array))
    return ($_i == $c-1) ? $array[$k] : find_in_array($array[$k], $path, $_i+1);
  else
    return false;
}

Parameter $_i is for internal use and should not be set when calling the function.

Comments

0

not really elegant. but it works

$start = array('this', 'is', 'the', 'path')

$result[ $start[0] ][ $start[1] ][ $start[2] ][ $start[3] ] = array ();

1 Comment

Trouble is, that only works with a predefined array count - what if I don't know how many nodes there are in the path?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.