12

I've been looking a lot of answers, but none of them are working for me.

This is the data assigned to my $quantities array:

Array(
    [10] => Array([25.00] => 1)
    [9] => Array([30.00] => 3)
    [8] => Array([30.00] => 4)
    [12] => Array([35.00] => )
    [1] => Array([30.00] => )
    [2] => Array([30.00] => )
)

I'm looking for a way to remove the subarrays with empty values like [12] [1] and [2] while keeping everything else.

The desired result:

Array(
    [10] => Array([25.00] => 1)
    [9] => Array([30.00] => 3)
    [8] => Array([30.00] => 4)
)

I tried a lot of the functions on the official php docs and none of them worked.

I've used this one:

function array_filter_recursive($array, $callback = null) {
    foreach ($array as $key => & $value) {
        if (is_array($value)) {
            $value = array_filter_recursive($value, $callback);
        } else {
            if ( ! is_null($callback)) {
                if ( ! $callback($value)) {
                    unset($array[$key]);
                }
            } else {
                if ( ! (bool) $value) {
                    unset($array[$key]);
                }
            }
        }
    }
    unset($value);
    return $array;
}

But it only removes the element in the subarrays; I need the subarrays to be removed entirely.

I don't want this:

Array(
    [10] => Array([25.00] => 1)
    [9] => Array([30.00] => 3)
    [8] => Array([30.00] => 4)
    [12] => Array()
    [1] => Array()
    [2] => Array()
)
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Richard-MX
  • 484
  • 1
  • 6
  • 16
  • Consider using var_dump() instead to show us the array contents. – Ja͢ck May 14 '13 at 11:57
  • For a page that is used as a destination for so many dupe links, this page has an amazing amount of upvoted incorrect answers. @Richard-MX I have posted an answer that doesn't use recursion or multiple iterating functions so that readers that are trafficked here are able to see a lean working (zero-safe) solution. (it is unclear in your post if your empty arrays have empty strings or `null` as values, so I demo'ed with both) – mickmackusa Oct 15 '17 at 14:06

9 Answers9

20

Bit late, but may help someone looking for same answer. I used this very simple approach to;

  1. remove all the keys from nested arrays that contain no value, then
  2. remove all the empty nested arrays.

$postArr = array_map('array_filter', $postArr);
$postArr = array_filter( $postArr );
Chris
  • 8,527
  • 10
  • 34
  • 51
Alastair F
  • 226
  • 2
  • 4
6

The following function worked for my case. We can use a simple recursive function to remove all empty elements from the multidimensional PHP array:

function array_filter_recursive($input){
    foreach ($input as &$value){
        if (is_array($value)){
            $value = array_filter_recursive($value);
        }
    }
    return array_filter($input);
}

Then we just need to call this function:

$myArray = array_filter_recursive($myArray);
Reza Mamun
  • 5,991
  • 1
  • 43
  • 42
2

Not sure if this is exactly what your looking for.

function array_remove_null($array) {
    foreach ($array as $key => $value)
    {
        if(is_null($value))
            unset($array[$key]);
        if(is_array($value))
            $array[$key] = array_remove_null($value);
    }
    return $array;
}

Update (corrections):

function array_remove_null($array) {
    foreach ($array as $key => $value)
    {
        if(is_null($value))
            unset($array[$key]);
        if(is_string($value) && empty($value))
            unset($array[$key]);
        if(is_array($value))
            $array[$key] = array_remove_null($value);
        if(isset($array[$key]) && count($array[$key])==0)
            unset($array[$key]);
    }
    return $array;
}

I'm sure better checking and making this more robust might help the solution.

Jason Foglia
  • 2,414
  • 3
  • 27
  • 48
  • Hello Jason, thanks for your reply. Unfortunately, it doesn't work for what i need. As Paul answer, it returns the same as the original question. – Richard-MX Apr 18 '12 at 17:44
  • I'm not sure why this has 4 upvotes. This code-only answer does not work. [Demo](http://sandbox.onlinephpfunctions.com/code/a06f86d99043713158cb6170b516ffebd9533f4a) – mickmackusa Oct 15 '17 at 13:59
  • @mickmackusa this example worked back in the days of PHP 5. – Jason Foglia Oct 16 '17 at 18:21
  • @JasonFoglia There is nothing version specific that is impacting your answer. It doesn't work in php5 either. [PHP 5.5.0.a.2 Demo](http://sandbox.onlinephpfunctions.com/code/1a570d9598a8c366ad3864fa9884f42f1a17af76) – mickmackusa Oct 16 '17 at 21:39
  • @mickmackusa This answer answers the question. How to remove VALUES from an array; not empty arrays from arrays. – Jason Foglia Oct 16 '17 at 22:27
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/156933/discussion-between-jason-foglia-and-mickmackusa). – Jason Foglia Oct 17 '17 at 16:15
0

use array_map() for filter every array in $array:

$newArray = array_map('array_filter', $array);

Here's demo

Naitik Shah
  • 513
  • 6
  • 13
  • 1
    This answer DOESN'T WORK. It doesn't work in the posted demo link. It doesn't work in [my demo link](http://sandbox.onlinephpfunctions.com/code/e8b7659f6b504afea691451351c039de24c0a7f4) How in the world did this earn 3 upvotes? Downvote from me. – mickmackusa Oct 15 '17 at 13:53
0
$newArray = array_map('array_filter', $array);

This sintax it's work and very help full thank's guys ..

Jakfar Shodiq
  • 59
  • 2
  • 7
  • 1
    This is an exact duplicate method (character for character) of NaitikShah's answer that was posted two months earlier. If you cannot improve your answer to provide better information you should delete this answer because it does not add value to the page (it is merely page bloat). – mickmackusa Oct 15 '17 at 13:24
  • 1
    This answer DOESN'T WORK. It doesn't work in [my demo link](http://sandbox.onlinephpfunctions.com/code/e8b7659f6b504afea691451351c039de24c0a7f4) How in the world did this earn 3 upvotes? Downvote from me. – mickmackusa Oct 15 '17 at 13:53
0

Use array_filter with array_map like below:

$arr=array_filter(array_map('array_filter', $arr));
lalithkumar
  • 3,480
  • 4
  • 24
  • 40
  • 1
    This is not new information. This is a duplicate of [AlastairF's answer](https://stackoverflow.com/a/18796083/2943403) written as a one-liner. – mickmackusa Oct 17 '17 at 03:24
0

This one worked for me

function array_filter_recursive($input){
    foreach ($input as &$value){
        if (is_array($value)){
            $value = array_filter_recursive($value);
        }
    }
    return array_filter($input);
}
-1

This removes all items with null values recursively on multideminsional arrays. Works on PHP >= 5.6. If you want to remove all "empty" values, replace !is_null($value) with !empty($value).

function recursivelyRemoveItemsWithNullValuesFromArray(array $data = []): array
{
    $data = array_map(function($value) {
        return is_array($value) ? recursivelyRemoveItemsWithNullValuesFromArray($value) : $value;
    }, $data);

    return array_filter($data, function($value) {
        return !is_null($value);
    });
}
HKandulla
  • 1,101
  • 12
  • 17
  • 1
    This answer does not provide the OP's desired output. [Demo](http://sandbox.onlinephpfunctions.com/code/c30daafe3cf0959e0a0c4dcaa901244605a8f7d9) – mickmackusa Oct 18 '17 at 01:58
  • @mickmackusa As stated in my answer "If you want to remove all "empty" values, replace !is_null($value) with !empty($value)". You Demo works as expected. I updated your demo using empty() instead of is_null(). Please check: http://sandbox.onlinephpfunctions.com/code/bf91c085d8ed75da7854d1e4814495d06cc1fa04 – HKandulla Aug 02 '19 at 08:40
-4

Because the subarrays in your array only have one element each, you can simplify the approach using either of the two following methods. The logical advantage is in avoiding the functional iterator (array_filter) on the second level elements. This is why current() is more suitable for this question/page.

Code: (Demo)

$quantities=[
    10=>['25.00'=>1],
    9=>['30.00'=>3],
    8=>['30.00'=>4],
    12=>['35.00'=>null],
    1=>['30.00'=>''],
    2=>['30.00'=>null]
];

var_export(array_filter($quantities,function($a){return strlen(current($a));}));

OR

foreach($quantities as $key=>$sub){  // could be done "by reference" but that impacts code stability
    if(!strlen(current($sub))){  // if subarray value has no length
        unset($quantities[$key]);
    }
}
var_export($quantities);

Both output the same result (which purposely removes empty values and preserves 0 values)

array (
  10 => 
  array (
    '25.00' => 1,
  ),
  9 => 
  array (
    '30.00' => 3,
  ),
  8 => 
  array (
    '30.00' => 4,
  ),
)

In the above methods, strlen() is used to check the 2nd level elements because the OP only listed integers as the "non-empty" values. Future SO readers may have different requirements based on the elements possibly holding false, null, '0', 0, etc. Suitable replacement functions for strlen() may be: any of the "is_" functions, empty(), any of the "ctype" functions, and many more.

If the OP's 2nd level array held more than one element AND the OP wanted to remove all zero-ish, false-y, empty, null elements (meaning zeros are not wanted or guaranteed not to occur), then Alastair F's answer would be the best choice.

If the OP's input array had an unknown number of levels AND zero-ish/false-y/empty/null elements should be removed, then Reza Mamun's answer is a logical, recursive approach.

My point being (and my motivation behind spending so much time and care to answer this question) that array_filter() is greedy and if you aren't aware of this default behavior, your project may silently output incorrect information. I hope this explanation saves programmers some time and strife.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136