16

I have the following array that I need to recursively loop through and remove any child arrays that have the key 'fields'. I have tried array filter but I am having trouble getting any of it to work.

$myarray = array(
    'Item' => array(
        'fields' => array('id', 'name'),
        'Part' => array(
            'fields' => array('part_number', 'part_name')
        )
    ),
    'Owner' => array(
        'fields' => array('id', 'name', 'active'),
        'Company' => array(
            'fields' => array('id', 'name',),
            'Locations' => array(
                'fields' => array('id', 'name', 'address', 'zip'),
                'State' => array(
                    'fields' => array('id', 'name')
                )
            )
        )
    )    
);

This is how I need it the result to look like:

$myarray = array(
    'Item' => array(
        'Part' => array(
        )
    ),
    'Owner' => array(
        'Company' => array(
            'Locations' => array(
                'State' => array(
                )
            )
        )
    )    
);
2
  • What value will "Part" have after the remove action? Commented Nov 10, 2009 at 15:41
  • I just need to unset 'fields' and leave part as 'array()' Commented Nov 10, 2009 at 15:44

11 Answers 11

45

If you want to operate recursively, you need to pass the array as a reference, otherwise you do a lot of unnecessarily copying:

function recursive_unset(&$array, $unwanted_key) {
    unset($array[$unwanted_key]);
    foreach ($array as &$value) {
        if (is_array($value)) {
            recursive_unset($value, $unwanted_key);
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I'm not sure this is correct. From the php manual: If a variable that is PASSED BY REFERENCE is unset() inside of a function, only the local variable is destroyed. The variable in the calling environment will retain the same value as before unset() was called. php.net/manual/en/function.unset.php
@Gerbus: That statement only applies to the variable itself, not its values (or array-keys in this case). Altering the array itself does not invalidate the reference to the passed array. In other words: You would be correct if the code contained unset($array);, but this code unsets an array key.
5

you want array_walk

function remove_key(&$a) {
   if(is_array($a)) {
        unset($a['fields']);
        array_walk($a, __FUNCTION__);
   }
}
remove_key($myarray);

3 Comments

Doesn't array_walk state that if you unset an element that the “behavior of this function is undefined, and unpredictable”?
@greatwitenorth, it does say that. This might work, but its probably best to avoid it sadly.
doesn't work in php 7 as passing by reference has been deprecated
2

My suggestion:

function removeKey(&$array, $key)
{
    if (is_array($array))
    {
        if (isset($array[$key]))
        {
            unset($array[$key]);
        }
        if (count($array) > 0)
        {
            foreach ($array as $k => $arr)
            {
                removeKey($array[$k], $key);
            }
        }
    }
}

removeKey($myarray, 'Part');

2 Comments

isset is not best at this case, should use array_key_exists <?php $a = ['key' => null]; var_dump(isset($a['key'])); //returns false var_dump(array_key_exists('key', $a)); //returns true
Just a note for someone who stumbles across this: You dont need to check for isset before unset. unset does nothing if var is not set. You dont need to count an array before foreach. foreach does nothing if array is empty.
2
function recursive_unset(&$array, $unwanted_key) {

    if (!is_array($array) || empty($unwanted_key)) 
         return false;

    unset($array[$unwanted_key]);

    foreach ($array as &$value) {
        if (is_array($value)) {
            recursive_unset($value, $unwanted_key);
        }
    }
}

Comments

1
function sanitize($arr) {
    if (is_array($arr)) {
        $out = array();
        foreach ($arr as $key => $val) {
            if ($key != 'fields') {
                $out[$key] = sanitize($val);
            }
        }
    } else {
        return $arr;
    }
    return $out;
}

$myarray = sanitize($myarray);

Result:

array (
  'Item' => 
  array (
    'Part' => 
    array (
    ),
  ),
  'Owner' => 
  array (
    'Company' => 
    array (
      'Locations' => 
      array (
        'State' => 
        array (
        ),
      ),
    ),
  ),
)

Comments

1
function removeRecursive($haystack,$needle){
    if(is_array($haystack)) {
        unset($haystack[$needle]);
        foreach ($haystack as $k=>$value) {
            $haystack[$k] = removeRecursive($value,$needle);
        }
    }
    return $haystack;
}

$new = removeRecursive($old,'key');

Comments

1

Code:

$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => $sweet);

function recursive_array_except(&$array, $except)
{
  foreach($array as $key => $value){
    if(in_array($key, $except, true)){
      unset($array[$key]);
    }else{
      if(is_array($value)){
        recursive_array_except($array[$key], $except);
      }
    }
  }
  return;
}

recursive_array_except($fruits, array('a'));
print_r($fruits);

Input:

Array
(
    [sweet] => Array
        (
            [a] => apple
            [b] => banana
        )

    [sour] => Array
        (
            [a] => apple
            [b] => banana
        )

)

Output:

Array
(
    [sweet] => Array
        (
            [b] => banana
        )

    [sour] => Array
        (
            [b] => banana
        )

)

Comments

1

I come up with a simple function that you can use to delete multiple array element based on multiple keys.

Detail example here.

Just a little change in code.

function removeRecursive($inputArray,$delKey){
    if(is_array($inputArray)){
        $moreKey    =   explode(",",$delKey);
        foreach($moreKey as $nKey){
            unset($inputArray[$nKey]);
            foreach($inputArray as $k=>$value) {
                $inputArray[$k] = removeRecursive($value,$nKey);
            }
        }
    }
    return $inputArray;
}

$inputNew   =   removeRecursive($input,'keyOne,keyTwo');

print"<pre>";
print_r($inputNew);
print"</pre>";

Comments

0

Give this function a shot. It will remove the keys with 'fields' and leave the rest of the array.

function unsetFields($myarray) {
    if (isset($myarray['fields']))
        unset($myarray['fields']);
    foreach ($myarray as $key => $value)
        $myarray[$key] = unsetFields($value);
    return $myarray;
}

Comments

-1

Recursively walk the array (by reference) and unset the relevant keys.

clear_fields($myarray);
print_r($myarray);

function clear_fields(&$parent) {
  unset($parent['fields']);
  foreach ($parent as $k => &$v) {
    if (is_array($v)) {
      clear_fields($v);
    }
  }
}

Comments

-1

I needed to have a little more granularity in unsetting arrays and I came up with this - with the evil eval and other dirty tricks.

$post = array(); //some huge array

function array_unset(&$arr,$path){
    $str = 'unset($arr[\''.implode('\'][\'',explode('/', $path)).'\']);';
    eval($str);
}

$junk = array();
$junk[] = 'property_meta/_edit_lock';
$junk[] = 'property_terms/post_tag';
$junk[] = 'property_terms/property-type/0/term_id';
foreach($junk as $path){
    array_unset($post,$path);
}

// unset($arr['property_meta']['_edit_lock']);
// unset($arr['property_terms']['post_tag']);
// unset($arr['property_terms']['property-type']['0']['term_id']);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.