3

I have a hierarchical array path in a flat PHP array, e.g.: $path = array('fruit', 'banana', 'fresh');

I define my multidimensional array as $tree. How would you use $path to set/get the appropriate node in $tree? $tree[$path] = 'blablabl'; throws an "Illegal offset error". I'm not sure how I would implode() the path to a string and use eval() to get the index. What's the most straightforward way to do this?

2 Answers 2

3

Because an array is an array and PHP doesn't know anything about trees you must resolve the path against your multidimensional array yourself, but thats not hard.

Iterativ

$result = $tree;
foreach ($path as $step) {
  $result = $result[$step];
}

or recursive

function resolve_tree ($tree, $path) {
  return empty($path)
         ? $tree
         : resolve_tree ($tree[$path[0]], array_slice($path, 1));
}

Note, that this are the simplest solutions. For example you should take care, that a given key from $path exists, before you try to access it.

Update: I overlooked the "set"-part in the question. Without references its not that funny, thus I suggest to completely switch over to objects instead of arrays. Its not required, that you create a class. You can simply use stdClass. This would even feel a little bit more "tree"ish

Sign up to request clarification or add additional context in comments.

3 Comments

I'm trying to create $tree[$path], your methods work for getting a node but not setting one.
$path is an array and I forgot an index there. See my update above. An yes, I didn't look at "set"
I'm kind of stumped, I'm using your object method: pastebin.com/NN1t87HK Is this what you had in mind?
2

I solved the same problem with references:

function &walk_path(array &$root, array $path)
{
    $cursor = &$root;
    foreach ($path as $e) { $cursor = &$cursor[$e]; }
    return $cursor;
}

$db = [];
$tmp = &walk_path($db, ["users","deanna", "favourite food"]);
$tmp = "chocolate";
print_r($db);

will produce

Array
(
    [users] => Array
        (
            [deanna] => Array
                (
                    [favourite food] => chocolate
                )

        )

)

Note that since PHP autovivicates this will create any non-existent keys either as an array with the only key being the next elemenet in the path or null if it is the leaf node. This is fortunately exactly the behaviour I needed. However, it still strikes me as a bit akward that I have to write this function myself in a lanuage so focused on its arrays. Any suggestions to make this shorter are very welcome.

2 Comments

Note: Assigning the input variable to have a value in the path with a non-array causes an error. $db = ['users'=>1];
"it still strikes me as a bit akward that I have to write this function myself in a lanuage so focused on its arrays" - That's what I thought too.

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.