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

问题描述 投票:0回答:9

我需要删除多级数组上的空条目。现在我可以删除带有空子数组的条目,但不能删除空数组...很困惑,我也是...我认为代码将有助于更好地解释。

/**
 * 
 * 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));

此代码将删除

nickname
birthdate
,但不会删除具有空数组的
bikes

我的问题是...如何删除

bikes
条目?

php arrays recursion is-empty array-filter
9个回答
43
投票

试试这个代码:

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

2
投票

这是我的解决方案,它将递归地删除精确指定的空值列表:

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

你可以这样使用它:

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

注意,如果您将

[]
作为值之一传递,它会删除空子数组。


2
投票
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 => "   ",
   ]

0
投票

我认为这应该可以解决你的问题。

$retArray =array_filter($array, arrayFilter);

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

0
投票

递归清除空项的多维数组:

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

单元测试:

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

在 3v4l.org 进行概念验证


0
投票

基于递归函数的简单而优雅的解决方案。不喜欢上一个解决方案。答案。删除空子数组/子值:

/**
 * Clean array from empty values
 * @param $array
 * @return array|mixed
 */
function array_filter_recursive($array){
    if (!is_array($array)) return $array;
    foreach ( $array as $key=>$item){
        if (is_array($item))
            $array[$key] = array_filter_recursive($item);
    }
    return array_filter($array);
}

0
投票

array_filter()
empty()
对于提问者的样本输入来说可能是安全的,但它们对于公众一般用途来说并不可靠。这些本机函数会将所有“错误”值视为可过滤/空。有关其贪婪确定空性的详细信息,请参阅 empty()
 的文档。

我建议显式检查(特别是数据类型)是否有空字符串(如果这是意图)。这样您就不会无意中破坏有意义的数据。我选择将

$value

 声明为引用以避免迭代数组的副本 - 这允许我使用 
$value
 而不是更详细的 
$array[$key]
 来改变/覆盖数组数据(当不使用 
unset()
 时)。 

代码:(

带有各种错误值的演示

function recursivelyRemoveEmpties(array $array): array { foreach ($array as $key => &$value) { if (is_array($value)) { $value = recursivelyRemoveEmpties($value); if (!$value) { unset($array[$key]); } continue; } if ($value === '') { unset($array[$key]); } } return $array; } var_export(recursivelyRemoveEmpties($raw));

*请注意,此脚本并非旨在容纳数据有效负载中的对象。


-1
投票
我的功能:

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

-2
投票
如果您希望 array_filter 递归工作,您需要确保后续调用可以编辑数组的更深层次的嵌套项。简而言之:您需要通过引用传递它:

function removeEmptyItems(&$item) { if (is_array($item) && $item) { $item = array_filter(&$item, 'removeEmptyItems'); } return !!$item; }
    
© www.soinside.com 2019 - 2024. All rights reserved.