3

i'd like to remove a specific sub array by a dot-separated key. Here's some working (yes it's working but not even close to a nice solution) code:

$Data = [
                'one',
                'two',
                'three' => [
                    'four' => [
                        'five' => 'six', // <- I want to remove this one
                        'seven' => [
                            'eight' => 'nine'
                        ]
                    ]
                ]
            ];

            # My key
            $key = 'three.four.five';
            $keys = explode('.', $key);
            $str = "";
            foreach ($keys as $k) {
                $sq = "'";
                if (is_numeric($k)) {
                    $sq = "";
                }
                $str .= "[" . $sq . $k . $sq . "]";
            }
            $cmd = "unset(\$Data{$str});";
            eval($cmd); // <- i'd like to get rid of this evil shit

Any ideas for a more nice solution on this?

Link
  • 33
  • 3

2 Answers2

1

You could use references to the elements inside the array and then remove the last key of your $keys array.

You should add some error handling / checking if the keys actually exist, but this is the basis:

$Data = [ 
            'one',
            'two',
            'three' => [
                'four' => [
                    'five' => 'six', // <- I want to remove this one
                    'seven' => [
                        'eight' => 'nine'
                    ]
                ]
            ]
];

# My key
$key = 'three.four.five';
$keys = explode('.', $key);

$arr = &$Data;
while (count($keys)) {
    # Get a reference to the inner element
    $arr = &$arr[array_shift($keys)];

    # Remove the most inner key
    if (count($keys) === 1) {
        unset($arr[$keys[0]]);
        break;
    }
}

var_dump($Data);

A working example.

jeroen
  • 91,079
  • 21
  • 114
  • 132
1

You can do this by using references. Important to note is that you can not unset variable, but you can unset a array key.

A solution is the following code

# My key
$key = 'three.four.five';
$keys = explode('.', $key);
// No change above here


// create a reference to the $Data variable
$currentLevel =& $Data;
$i = 1;
foreach ($keys as $k) {
    if (isset($currentLevel[$k])) {
        // Stop at the parent of the specified key, otherwise unset by reference does not work
        if ($i >= count($keys)) {
            unset($currentLevel[$k]);
        }
        else {
            // As long as the parent of the specified key was not reached, change the level of the array
            $currentLevel =& $currentLevel[$k];
        }
    }
    $i++;
}
Jelmergu
  • 973
  • 1
  • 7
  • 19