hendr1x
hendr1x

Reputation: 1501

Unset a specific variable within a multidimensional array

I can't figure out how do this at all. My first attempt involved using references and calling unset on a reference simply unlinks the reference. I tried recursion but couldn't get it to work, I then tried array_walk and array_filter without success. Here is a simple example that demonstrates what I am trying to do.

<?
class Sample {
    //Please note this can have a completely variable amount of vars/dimensions
    $data = array("system" => array("value1","value2"), "session" => array("value1"));

    public function erase($value){
         //Here I am suppose to somehow delete that exists in $this->data
    }
    public function display(){
         print_r($this->data);
    }
 }


 $Sample = new Sample();
 $Sample->erase(array("system","value1"));
 //I am extremely flexible on the format of the erase parameter ($value)
 $Sample->display();

 should output with the variable unset($this->data["system"]["value1"]) :

 array("system" => array("value2"), "session" => array("value1")

Ohgodwhy helped by creating a eval.in with a slighly modified example

Thank you for your help

Upvotes: 1

Views: 51

Answers (2)

Adam Sinclair
Adam Sinclair

Reputation: 1649

I've made this function and work pretty great.

function erase(array &$arr, array $children)
{
    $ref = &$arr;
    foreach ($children as $child)
        if (is_array($ref) && array_key_exists($child, $ref)) {
            $toUnset = &$ref;
            $ref = &$ref[$child];
        } else
            throw new Exception('Path does\'nt exist');
    unset($toUnset[end($children)]);
}

Example 1:

Here's an example of how you would unset $arr['session']['session3']['nestedSession2']

$arr = [
    "system" => [
        "system1" => "value1",
        "system2" => "value2"
    ],
    "session" => [
        "session1" => "value3",
        "session2" => "value4",
        "session3" => [
            "nestedSession1" => "value5",
            "nestedSession2" => "value6",
        ],
    ],
];

print_r($arr);
erase($arr, array('session', 'session3', 'nestedSession2'));
print_r($arr);

Example 2:

It can even unset a whole nested array, here's how you would do it (handling errors):

print_r($arr);
try {
    erase($arr, array('session', 'session3'));
}  catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
print_r($arr);

Example 3:

It also work with non-assiociative array:

$arr = array('fruit1', 'fruit2', 'fruit3');
print_r($arr);
try {
    erase($arr, array(0));
}  catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
print_r($arr);

Example 4:

In case of error:

$arr = array('fruit1', 'fruit2', 'fruit3');
print_r($arr);
try {
    erase($arr, array('pathThatDoesNotExit'));
}  catch (Exception $e) {
    // do what you got to do here in case of error (if the path you gave doesn't exist)!
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}
print_r($arr);

Upvotes: 1

Ohgodwhy
Ohgodwhy

Reputation: 50787

If you'll always be passing in the key name of the array that contains the value, followed by the value, we can use array_search to perform this.

if(false !== $key = array_search($value[1], $this->data[$value[0]])):
    unset($this->data[$value[0]][$key]);
endif;

Here's your eval.in example

Upvotes: 1

Related Questions