PRK
PRK

Reputation: 13

How to create a reference to a value nested in a multidimensional array given an arbitrary amount of indexes

I have a class that works with a nested array and I want to perform operations on a value somewhere in that nested array, given an arbitrary set of indexes.

I'm using a reference to refer to the value that is being manipulated.

class Test {
    function __construct(){
       // just an example of a multi dimensional array to work with
       $this->data = array(
          array( 10, 100, 1000),
          array( 20, 200, 2000),
          array( 
               array( 30, 300, 3000), 
               array( 40, 400, 5000),
               array( 50, 400, 5000)
          )
       );
    }

    function set_reference( $indexes ){
        // set reference to a value somewhere inside $this->data
        $this->current = &$this->data[$not][$sure]; // but how
        return $this;
    }

    function add_three(){
        $this->current += 3;
        return $this;
    }

    function render(){
        var_dump( $this->current );
        return $this;
    }
}

This example would then be able to work something like this.

$test = new Test();
$test->set_reference( array( 1, 1 ) )->add_three()->render(); // should show 203
$test->set_reference( array( 2, 1, 1 ) )->add_three()->render(); // should show 403

I'm struggling with this, especially because there doesn't seem to be a convenient way to access a value inside a nested array given a variable number of indexes. The closest I've gotten is by using eval, but eval seems out of place and doesn't work in all environments which is a nonstarter.

$indexes = "[2][1][1]"; // or "[1][1]" or "[0]" 
eval( 
    "if( isset( $this->data" . $indexes . " ) ) { 
        $this->current = &$this->data" . $indexes . ";
    }" 
);

I have also tried doing something with a loop to retrieve the nested value, but I don't know how to change the value $this->current refers to without modifying $this->data.

Upvotes: 1

Views: 92

Answers (1)

Amber
Amber

Reputation: 526623

Use a loop to walk through the index list, keeping a reference as you go.

function set_reference( $indexes ){
    $current = &$this->data;
    foreach($indexes as $index) {
        $current = &$current[$index];
    }
    $this->current = &$current;
    return $this;
}

(If you don't want later modifications to $this->current to affect $this->data, then drop the &s.)

Upvotes: 1

Related Questions