【问题标题】:Using string path to delete element from array使用字符串路径从数组中删除元素
【发布时间】:2013-05-17 21:29:36
【问题描述】:

我有这样的数组

$arr = [
   'baz' => [
      'foo' => [
         'boo' => 'whatever'
     ]
   ]
];

是否可以使用字符串输入来取消设置 ['boo'] 的值?

类似的东西

    $str = 'baz->foo->boo';
    function array_unset($str, $arr) {

    // magic here

    unset($arr['baz']['foo']['boo']);
    return $arr;
    }

这个答案太棒了,它使我的脚本的第一部分运行Using a string path to set nested array data .但无法逆转。 附言eval() 不是一个选项:(

【问题讨论】:

    标签: php arrays unset


    【解决方案1】:

    由于不能在引用的元素上调用 unset,你需要使用另一个技巧:

    function array_unset($str, &$arr)
    {
        $nodes = split("->", $str);
        $prevEl = NULL;
        $el = &$arr;
        foreach ($nodes as &$node)
        {
            $prevEl = &$el;
            $el = &$el[$node];
        }
        if ($prevEl !== NULL)
            unset($prevEl[$node]);
        return $arr;
    }
    
    $str = "baz->foo->boo";
    array_unset($str, $arr);
    

    本质上,您遍历数组树,但保留对要从中删除节点的最后一个数组(倒数第二个节点)的引用。然后在最后一个数组上调用unset,将最后一个节点作为键传递。

    Check this codepad

    【讨论】:

    • 该死的......它很聪明。顺便说一句,有 2 个问题。 1)你为什么使用拆分?简单的爆炸工作完全没问题。 2)为什么你把 $arr 参数引用?
    • 1) 上周大量使用 Qt/C#,他们倾向于使用“拆分”,explode 会很好用。 2)你需要一直保持对原始数组的引用,否则unset只会从副本中移除节点而不是原始数组。
    • 如果您在参数中传递了数组变量的名称,则可以使用 $GLOBALS 代替。 (来自文档:要取消设置()函数内部的全局变量,然后使用 $GLOBALS 数组来做
    • @antoox:使用 $GLOBALS 期望您的数组在全局范围内定义,我倾向于避免这种情况。我的答案中的代码更具可移植性,并且可以很容易地用于以 OO 方法工作。
    • 我的 $arr 参数取自对象。无论如何,它不能被那个函数改变......这就是为什么我对引用它感到困惑。在我看来,设置和取消设置全局变量有点额外的工作,这里不需要
    【解决方案2】:

    这个类似于 Wouter Huysentruit 的。不同的是,如果你传递了一个无效的路径,它会返回 null。

    function array_unset(&$array, $path)
    {
        $pieces = explode('.', $path);
        $i = 0;
        while($i < count($pieces)-1) {
            $piece = $pieces[$i];
            if (!is_array($array) || !array_key_exists($piece, $array)) {
                return null;
            }
            $array = &$array[$piece];
            $i++;
        }
        $piece = end($pieces);
        unset($array[$piece]);
        return $array;
    }
    

    【讨论】:

      【解决方案3】:

      可能对你有用的东西:

      $str = 'bar,foo,boo';
      
      function array_unset($str,&$arr) {
        $path = explode(',',$str);
        $buf = $arr;
        for($i=0;$i<count($path)-1;$i++) {
          $buf = &$buf[$path[$i]];
        }
      
        unset($buf);
      }
      

      【讨论】:

      • 它不起作用。来自documentation如果通过引用传递的变量在函数内部是 unset(),则只有局部变量被破坏。调用环境中的变量将保持与调用 unset() 之前相同的值。
      • 不...它不会影响 $arr 本身。
      猜你喜欢
      • 2015-06-23
      • 2020-08-29
      • 2023-04-09
      • 2017-12-24
      • 1970-01-01
      • 1970-01-01
      • 2022-10-05
      • 1970-01-01
      • 2022-11-16
      相关资源
      最近更新 更多