views:

290

answers:

5

What's the best way to remove the parent of a matched key in an Multidimensional Array? For example, let's assume we have the following array and I want to find "[text] = a" and then delete its parent array [0]...

(array) Array
(

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

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

The inner arrays don't maintain any reference to their "parent" arrays, so you'd have to write a function to manually track this. Something like this might work:

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

Note that this is designed to work at any level of nesting, not just two dimensions, so it might be a bit of overkill if you only need it for situations like in your example.

nickf
take note, the array key may not be numeric.
thephpdeveloper
@thephpdeveloper: fixed that up now, thanks.
nickf
+3  A: 

Here’s the obvious:

foreach ($array as $key => $item) {
    if ($item['text'] === 'a') {
        unset($array[$key]);
    }
}
Gumbo
this works in a 2 dimensional array, but not in general multidimensional arrays.
nickf
This was my first guess but, like you said, it's not recursive. Maybe, pushing it a bit more might help...
Andres
@Andres: Then how does such a multidimensional array look like where you would need recursion?
Gumbo
It worked!.. It's sometimes difficult to capture the representational meaning of arrays. I've always used $key => $val and didn't consider $key => $item...@Gumbo what if (in my example) [text] = array( [title] = "Hello", [body] = "this is a test" )and I wanted to find and delete the parent of [title] = hello, which is [text]
Andres
@Andres: Try `if ($item['text']['title'] === '…') unset($array[$key]['text']);`.
Gumbo
+2  A: 

using array_filter:

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

this will only leave 'parent elements' in the array where text != a, therefore deleting those where text equals a

knittl
@anonymous down-voter: what's wrong with my solution??
knittl
A: 

My implementation:

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

To test it:

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

This function does it recursively.

thephpdeveloper
A: 

A simple and safe solution(I'd not remove/unset elements from an array I'm looping through) could be:

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