簡體   English   中英

從多維數組中刪除深層嵌套的元素?

[英]Remove deeply nested element from multi-dimensional array?

我需要從一個未知結構的深層嵌套數組中刪除一個元素(即,我不知道要取消設置該元素的鍵序列是什么)。 但是,我要刪除的元素確實具有一致的結構(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] ,其中該目標是一個具有三個字段的數組:

  • 領域
  • 算子

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

這只是一個游標問題。

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);

解決此問題的一種方法是使用第二個參數擴展遞歸函數:

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

您仍然可以用相同的方式進行初始調用,但是內部調用本身是這樣的:

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

這將為您提供鍵的完整路徑,以到達$keyPath變量中數組的當前部分。 然后,您可以在未unset使用它。 如果您真的很臟,您甚至可以使用eval作為有效的快捷方式,因為您輸入的輸入源將完全在您的控制之內。

編輯:另一方面,當您遍歷數組時,從數組中刪除項目可能不是一個好主意。 我不確定foreach的編譯方式,但是如果遇到奇怪的錯誤,您可能希望將查找邏輯與刪除邏輯分開。

我已經找到了一個解決方案,該解決方案是從http://www.php.net/manual/en/function.array-search.php#79535(array_search文檔)中找到的函數的array_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,因為它是一個巨大的,巨大的安全漏洞的SCREAMS,但它非常安全,並且eval中調用的值是由Drupal核心和Views顯式生成的。 我現在可以使用它了。

無論如何,當我返回樹時,我只是用新返回的樹數組替換了舊的數組。 奇跡般有效。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM