0

我需要从一个深度嵌套的未知结构数组中删除一个元素(即,我不知道要取消设置该元素的键序列是什么)。但是,我要删除的元素确实具有一致的结构 (stdObject),因此我可以搜索整个多维数组以找到它,但必须将其删除。关于如何实现这一点的想法?

编辑:这是我现在试图实现的功能。

function _subqueue_filter_reference(&$where)
{
    foreach ($where as $key => $value) {
        if (is_array($value))
        {
            foreach ($value as $filter_key => $filter)
            {
                if (isset($filter['field']) && is_string($filter['field']) && $filter['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
                {
                    unset($value[$filter_key]);
                    return TRUE;
                }
            }
            return _subqueue_filter_reference($value);
        }
    }
    return FALSE;
}

编辑#2:var_dump.

array (size=1)
  1 => 
    array (size=3)
      'conditions' => 
        array (size=5)
          0 => 
            array (size=3)
              ...
          1 => 
            array (size=3)
              ...
          2 => 
            array (size=3)
              ...
          3 => 
            array (size=3)
              ...
          4 => 
            array (size=3)
              ...
      'args' => 
        array (size=0)
          empty
      'type' => string 'AND' (length=3)

...因此假设将整个结构分配给$array,我需要删除的元素是$array[1]['conditions'][4]该目标是具有三个字段的数组:

  • 场地
  • 价值
  • 操作员

...所有这些都是字符串值。

4

3 回答 3

1

这只是一个游标问题。

function recursive_unset(&$array)
{
    foreach ($array as $key => &$value) # See the added & here.
    {
        if(is_array($value))
        {
            if(isset($value['field']) && $value['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
            {
                unset($array[$key]);
            }
            recursive_unset($value);
        }
    }
}

注意:您不需要在这里使用 is_string ,您可以在与字符串进行比较并且值存在时进行比较。

除非您确定您的值只出现一次,否则不要使用 return。

编辑 :

这是一个完整的示例,其中包含与您显示的类似的数组:

$test = array (
        1 => array (
                'conditions' =>
                array (
                        0 => array ('field' => 'dont_care1', 'value' => 'test', 'operator' => 'whatever'),
                        1 => array ('field' => 'dont_care2', 'value' => 'test', 'operator' => 'whatever'),
                        2 => array ('field' => 'nodequeue_nodes_node__nodequeue_subqueue.reference', 'value' => 'test', 'operator' => 'whatever'),
                        3 => array ('field' => 'dont_care3', 'value' => 'test', 'operator' => 'whatever')
                ),
        'args' => array (),
        'type' => 'AND'
));

var_dump($test);

function recursive_unset(&$array)
{
    foreach ($array as $key => &$value)
    {
        if(is_array($value))
        {
            if(isset($value['field']) && $value['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
            {
                unset($array[$key]);
            }
            recursive_unset($value);
        }
    }
}

recursive_unset($test);

var_dump($test);
于 2013-08-20T14:13:41.287 回答
0

我已经找到了一个解决方案,它是http://www.php.net/manual/en/function.array-search.php#79535array_search文档)中的函数的衍生产品。

代码:

function _subqueue_filter_reference($haystack,&$tree=array(),$index="")
{
    // dpm($haystack);
    if (is_array($haystack))
    {

        $result = array();

        if (count($tree)==0)
        {
            $tree = array() + $haystack;
        }

        foreach($haystack as $k=>$current)
        {
            if (is_array($current))
            {
                if (isset($current['field']) && is_string($current['field']) && $current['field'] == 'nodequeue_nodes_node__nodequeue_subqueue.reference')
                {
                    eval("unset(\$tree{$index}[{$k}]);"); // unset all elements = empty array
                }
                _subqueue_filter_reference($current,$tree,$index."[$k]");
            }
        } 
    } 
    return $tree;
}

我讨厌必须使用 eval,因为它会发出巨大的、巨大的安全漏洞,但它非常安全,并且在 eval 中调用的值是由 Drupal 核心和 Views 显式生成的。我现在可以使用它。

无论如何,当我返回树时,我只需用新返回的树数组替换旧数组。奇迹般有效。

于 2013-08-20T14:47:45.693 回答
0

解决此问题的一种方法是使用第二个参数扩展递归函数:

function _subqueue_filter_reference(&$where, $keyPath = array())

您仍然会以相同的方式进行初始调用,但对其自身的内部调用将是这样的:

return _subqueue_filter_reference($value, array_merge($keyPath, array($key)));

这将为您提供键的完整路径以到达$keyPath变量中数组的当前部分。然后你可以在你的unset. 如果你觉得很脏,你甚至可以使用eval它作为一个有效的快捷方式,因为你给它的输入源将完全在你的控制范围内。

编辑:另一方面,在循环遍历数组时从数组中删除项目可能不是一个好主意。我不确定 foreach 是如何编译的,但是如果您遇到奇怪的错误,您可能希望将查找逻辑与删除逻辑分开。

于 2013-08-20T13:59:05.770 回答