通过点分隔键删除多维数组中的子树

时间:2017-09-20 09:27:23

标签: php arrays

我想通过点分隔键删除特定的子数组。这里有一些工作(是的,它正在工作,但甚至没有接近一个很好的解决方案)代码:

$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

对此更好的解决方案的任何想法?

2 个答案:

答案 0 :(得分:1)

您可以使用对数组内元素的引用,然后删除$keys数组的最后一个键。

如果密钥确实存在,您应该添加一些错误处理/检查,但这是基础:

$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

答案 1 :(得分:1)

您可以使用references执行此操作。需要注意的重要一点是,您无法取消设置变量,但您可以unset a array key

解决方案是以下代码

# 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++;
}