Удалить родителя в многомерном массиве PHP

Каков наилучший способ удалить родителя совпадающего ключа в многомерном массиве? Например, предположим, что у нас есть следующий массив, и я хочу найти «[text] = a», а затем удалить его родительский массив [0]...

(array) Array
(

[0] => Array
    (
        [text] => a
        [height] => 30
    )

[1] => Array
    (
        [text] => k
        [height] => 30
    )
)

person Andres    schedule 07.03.2010    source источник
comment
Итак, вы не хотите удалять остаток массива parent и иметь только первый узел из массива parent?   -  person Adam Kiss    schedule 07.03.2010
comment
Представьте, что массив продолжался как [0], [1], [2], [3]... Я бы удалил или сдвинул [0].   -  person Andres    schedule 10.03.2010


Ответы (5)


Вот очевидное:

foreach ($array as $key => $item) {
    if ($item['text'] === 'a') {
        unset($array[$key]);
    }
}
person Gumbo    schedule 07.03.2010
comment
это работает в двумерном массиве, но не в многомерных массивах. - person nickf; 07.03.2010
comment
Это было мое первое предположение, но, как вы сказали, оно не рекурсивно. Может быть, еще немного подтолкнуть его и помочь... - person Andres; 10.03.2010
comment
@Andres: Тогда как выглядит такой многомерный массив, где вам понадобится рекурсия? - person Gumbo; 10.03.2010
comment
Это сработало!.. Иногда трудно уловить репрезентативное значение массивов. Я всегда использовал $key => $val и не рассматривал $key => $item... @Gumbo, что, если (в моем примере) [text] = array( [title] = Hello, [body] = это тест ) и я хотел найти и удалить родителя [title] = hello, который является [text] - person Andres; 10.03.2010
comment
@Андрес: Попробуйте if ($item['text']['title'] === '…') unset($array[$key]['text']);. - person Gumbo; 10.03.2010

используя array_filter:

function filter_callback($v) {
  return !isset($v['text']) || $v['text'] !== 'a';
}
$array = array_filter($array, 'filter_callback');

это оставит только «родительские элементы» в массиве, где text != a, поэтому удаляются те, где текст равен

person knittl    schedule 07.03.2010

Внутренние массивы не поддерживают никаких ссылок на свои «родительские» массивы, поэтому вам придется написать функцию, чтобы отслеживать это вручную. Что-то вроде этого может сработать:

function searchAndDestroy(&$arr, $needle) {
    foreach ($arr as &$item) {
        if (is_array($item)) {
            if (searchAndDestroy($item, $needle)) {
                return true;
            }
        } else if ($item === $needle) {
            $item = null;
            return true;
        }
    }
}

Обратите внимание, что это предназначено для работы на любом уровне вложенности, а не только в двух измерениях, поэтому это может быть немного излишним, если вам это нужно только для ситуаций, подобных вашему примеру.

person nickf    schedule 07.03.2010
comment
обратите внимание, ключ массива не может быть числовым. - person mauris; 07.03.2010

Простое и безопасное решение (я бы не стал удалять/удалять элементы из массива, который я просматриваю) может быть:

$new_array = array();
foreach($array as $item)
{
    if($item['text'] != "a")
    {
        $new_array[] = $item;
    }
}
person Stefan K    schedule 07.03.2010

Моя реализация:

function searchAndDestroy(&$a, $key, $val){
    foreach($a as $k => &$v){
        if(is_array($v)){
            $r = searchAndDestroy(&$v, $key, $val);
            if($r){
                unset($a[$k]);
            }
        }elseif($key == $k && $val == $v){
            return true;
        }
    }
    return false;
}

searchAndDestroy($arr, 'text', 'a');

Чтобы проверить это:

<pre><?php

function searchAndDestroy(&$a, $key, $val){
    foreach($a as $k => &$v){
        if(is_array($v)){
            $r = searchAndDestroy(&$v, $key, $val);
            if($r){
                unset($a[$k]);
            }
        }elseif($key == $k && $val == $v){
            return true;
        }
    }
    return false;
}

$arr = array(array('text'=>'a','height'=>'30'),array('text'=>'k','height'=>array('text'=>'a','height'=>'20')));

var_dump($arr);

searchAndDestroy($arr, 'text', 'a');

var_dump($arr);

?></pre>

Эта функция делает это рекурсивно.

person mauris    schedule 07.03.2010