一尘不染

如何通过键名/路径访问和操作多维数组?

php

我必须在PHP中实现一个 setter ,它允许我指定数组(目标)的键或子键,并将名称作为点分隔键值传递。

给出以下代码:

$arr = array('a' => 1,
             'b' => array(
                 'y' => 2,
                 'x' => array('z' => 5, 'w' => 'abc')
             ),
             'c' => null);

$key = 'b.x.z';
$path = explode('.', $key);

从价值$key我想达到的值 5$arr['b']['x']['z']

现在,给定变量值$key和不同的$arr值(深度不同)。

如何设置by引用的元素的值$key

对于 getter, get()我编写了以下代码:

public static function get($name, $default = null)
{
    $setting_path = explode('.', $name);
    $val = $this->settings;

    foreach ($setting_path as $key) {
        if(array_key_exists($key, $val)) {
            $val = $val[$key];
        } else {
            $val = $default;
            break;
        }
    }
    return $val;
}

写一个 setter 比较困难,因为我成功地从到达了正确的元素$key,但是我无法在原始数组中设置值,而且我也不知道如何一次全部指定键。

我应该使用某种回溯吗?还是可以避免?


阅读 307

收藏
2020-05-26

共1个答案

一尘不染

假设$path通过explode(或添加到函数)已经是一个数组,则可以使用引用。您需要添加一些错误检查以防无效$path等(请考虑isset):

$key = 'b.x.z';
$path = explode('.', $key);

吸气剂

function get($path, $array) {
    //$path = explode('.', $path); //if needed
    $temp =& $array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    return $temp;
}

$value = get($path, $arr); //returns NULL if the path doesn't exist

二传手/创造者

如果您传递的数组尚未定义,则此组合将在现有数组中设置一个值或创建该数组。确保定义$array要通过引用传递&$array

function set($path, &$array=array(), $value=null) {
    //$path = explode('.', $path); //if needed
    $temp =& $array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;
}

set($path, $arr);
//or
set($path, $arr, 'some value');

取消设定

这将unset是路径中的最终键:

function unsetter($path, &$array) {
    //$path = explode('.', $path); //if needed
    $temp =& $array;

    foreach($path as $key) {
        if(!is_array($temp[$key])) {
            unset($temp[$key]);
        } else {
            $temp =& $temp[$key];
        }
    }
}
unsetter($path, $arr);

*原始答案的功能有限,以防某些人使用它们:

塞特犬

确保定义$array要通过引用传递&$array

function set(&$array, $path, $value) {
    //$path = explode('.', $path); //if needed
    $temp =& $array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;
}

set($arr, $path, 'some value');

或者,如果您想返回更新的数组(因为感到无聊):

function set($array, $path, $value) {
    //$path = explode('.', $path); //if needed
    $temp =& $array;

    foreach($path as $key) {
        $temp =& $temp[$key];
    }
    $temp = $value;

    return $array;
}

$arr = set($arr, $path, 'some value');

创作者

如果您不想创建数组并选择设置值:

function create($path, $value=null) {
    //$path = explode('.', $path); //if needed
    foreach(array_reverse($path) as $key) {
        $value = array($key => $value);
    }
    return $value;
}

$arr = create($path);    
//or
$arr = create($path, 'some value');

为了娱乐

构造和计算类似于$array['b']['x']['z']给定字符串的内容b.x.z

function get($array, $path) {
    //$path = explode('.', $path); //if needed
    $path = "['" . implode("']['", $path) . "']";
    eval("\$result = \$array{$path};");

    return $result;
}

设置类似$array['b']['x']['z'] = 'some value';

function set(&$array, $path, $value) {
    //$path = explode('.', $path); //if needed
    $path = "['" . implode("']['", $path) . "']";
    eval("\$array{$path} = $value;");
}

取消类似的设置$array['b']['x']['z']

function unsetter(&$array, $path) {
    //$path = explode('.', $path); //if needed
    $path = "['" . implode("']['", $path) . "']";
    eval("unset(\$array{$path});");
}
2020-05-26