简体   繁体   English

PHP - 如何递归删除数组的空条目?

[英]PHP - How to remove empty entries of an array recursively?

I need to remove empty entries on multilevel arrays.我需要删除多级数组上的空条目。 For now I can remove entries with empty sub-arrays, but not empty arrays... confused, so do I... I think the code will help to explain better...现在我可以删除带有空子数组的条目,但不能删除空数组......困惑,我也是......我认为代码将有助于更好地解释......

<?php

/**
 * 
 * This function remove empty entries on arrays
 * @param array $array
 */
function removeEmptysFromArray($array) {

    $filtered = array_filter($array, 'removeEmptyItems');
    return $filtered;
}

/**
 * 
 * This is a Callback function to use in array_filter()
 * @param array $item
 */
function removeEmptyItems($item) {

    if (is_array($item)) {
        return array_filter($item, 'removeEmptyItems');
    }

    if (!empty($item)) {
        return true;  
    }
}


$raw = array(
    'firstname' => 'Foo',
    'lastname'  => 'Bar',
    'nickname' => '',
    'birthdate' => array( 
        'day'   => '',
        'month' => '',
        'year'  => '',
    ),
    'likes' => array(
        'cars'  => array('Subaru Impreza WRX STi', 'Mitsubishi Evo', 'Nissan GTR'),
        'bikes' => array(),
    ),
);

print_r(removeEmptysFromArray($raw));

?>

Ok, this code will remove "nickname", "birthdate" but is not removing "bikes" that have an empty array.好的,此代码将删除“昵称”、“生日”,但不会删除具有空数组的“自行车”。

My question is... How to remove the "bikes" entry?我的问题是...如何删除“自行车”条目?

Best Regards,此致,

Sorry for my english...对不起我的英语不好...

Try this code:试试这个代码:

<?php
function array_remove_empty($haystack)
{
    foreach ($haystack as $key => $value) {
        if (is_array($value)) {
            $haystack[$key] = array_remove_empty($haystack[$key]);
        }

        if (empty($haystack[$key])) {
            unset($haystack[$key]);
        }
    }

    return $haystack;
}

$raw = array(
    'firstname' => 'Foo',
    'lastname'  => 'Bar',
    'nickname' => '',
    'birthdate' => array(
        'day'   => '',
        'month' => '',
        'year'  => '',
    ),
    'likes' => array(
        'cars'  => array('Subaru Impreza WRX STi', 'Mitsubishi Evo', 'Nissan GTR'),
        'bikes' => array(),
    ),
);

print_r(array_remove_empty($raw));

I think this should solve your problem.我认为这应该可以解决您的问题。

$retArray =array_filter($array, arrayFilter);

function arrayFilter($array) {
     if(!empty($array)) {
         return array_filter($array);
     }
}

Here is my solution, it will remove exactly specified list of empty values recursively:这是我的解决方案,它将递归删除完全指定的空值列表:

/**
 * Remove elements from array by exact values list recursively
 *
 * @param array $haystack
 * @param array $values
 *
 * @return array
 */
function array_remove_by_values(array $haystack, array $values)
{
    foreach ($haystack as $key => $value) {
        if (is_array($value)) {
            $haystack[$key] = array_remove_by_values($haystack[$key], $values);
        }

        if (in_array($haystack[$key], $values, true)) {
            unset($haystack[$key]);
        }
    }

    return $haystack;
}

You can use it like this:你可以这样使用它:

$clean = array_remove_by_values($raw, ['', null, []]);

Note, it removes empty sub arrays if you pass [] as one of values.请注意,如果您将[]作为值之一传递,它会删除空的子数组。

Recursively clear multidimensional array of empty'ish items:递归清除空项目的多维数组:

final class ArrayCleaner
{
    public static function clean(array $value): array
    {
        foreach ($value as $k => $v) {
            if (\is_array($v)) {
                $value[$k] = self::clean($v);

                if (0 == \count($value[$k])) {
                    unset($value[$k]);
                }
            } elseif (empty($v)) {
                unset($value[$k]);
            }
        }

        return $value;
    }
}

Unit test:单元测试:

final class ArrayCleanerTest
{
    public function testItCleans(): void
    {
        $input = [
            'empty_string_to_remove' => '',
            'empty_int_to_remove' => 0,
            'empty_string_number_to_remove' => '0',
            'value_to_keep' => 5,
            'empty_array_to_remove' => [],
            'empty_array_of_empty_arrays_to_remove' => [
                'one' => [],
                'two' => [],
                'three' => [false, null, '0'],
            ],
            'array_to_keep_1' => [
                'value' => 1,
            ],
            'array_to_keep_2' => [
                'empty_to_remove' => [],
                'array_to_keep' => ['yes'],
            ],
        ];

        $expected = [
            'value_to_keep' => 5,
            'array_to_keep_1' => [
                'value' => 1,
            ],
            'array_to_keep_2' => [
                'array_to_keep' => ['yes'],
            ],
        ];

        $this->assertEquals($expected, ArrayCleaner::clean($input));
    }
}

Working proof of concept at 3v4l.org 3v4l.org 上的工作概念证明

My function:我的功能:

function removeEmptyItems($item)
{
    if (is_array($item)) {
        $item = array_filter($item, 'removeEmptyItems');
    }
    return !empty($item);
}

$nonEmpty = array_filter($raw, 'removeEmptyItems');
array_filter(explode('/', '/home/teste sdsd/   /'), 'trim');
//Result
[
     1 => "home",
     2 => "teste sdsd",
]

//-----------
array_filter(explode('/', '/home/teste sdsd/   /'), 'strlen')
//Result
  [
     1 => "home",
     2 => "teste sdsd",
     3 => "   ",
   ]

If you want array_filter to work recursively, you'll need to make sure that the subsequent calls may edit the deeper nested items of the array.如果您希望 array_filter 递归工作,则需要确保后续调用可以编辑数组的更深层嵌套项。 Short: You'll need to pass it by reference:简短:您需要通过引用传递它:

function removeEmptyItems(&$item) {
    if (is_array($item) && $item) {
        $item = array_filter(&$item, 'removeEmptyItems');
    }

    return !!$item;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM