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

发布于 2024-12-08 16:37:30 字数 1133 浏览 1 评论 0原文

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

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

此代码将删除nicknamebirthdate,但不会删除具有空数组的bikes

我的问题是...如何删除 bikes 条目?

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.

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

影子的影子 2024-12-15 16:37:30

试试这个代码:

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

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));
孤单情人 2024-12-15 16:37:30

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

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

注意,如果您将 [] 作为值之一传递,它会删除空子数组。

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.

淑女气质 2024-12-15 16:37:30
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 => "   ",
   ]
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 => "   ",
   ]
羁〃客ぐ 2024-12-15 16:37:30

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

$retArray =array_filter($array, arrayFilter);

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

I think this should solve your problem.

$retArray =array_filter($array, arrayFilter);

function arrayFilter($array) {
     if(!empty($array)) {
         return array_filter($array);
     }
}
小红帽 2024-12-15 16:37:30

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

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 进行概念验证

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

爱要勇敢去追 2024-12-15 16:37:30

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

如果这是意图的话,我建议显式检查(特别是数据类型)是否为空字符串。这样您就不会无意中破坏有意义的数据。我选择将 $value 声明为引用,以避免迭代数组的副本 - 这允许我使用 $value 而不是 more 来改变/覆盖数组数据详细 $array[$key] (不使用 unset() 时。

代码:(演示具有各种错误值

function recursivelyRemoveEmpties(array $array): array
{
    foreach ($array as $key => &$value) {  // modify by reference to affect original array
        if (is_array($value)) {
            $value = recursivelyRemoveEmpties($value);
            if (!$value) {  // if the array is empty
                unset($array[$key]);
            }
            continue;
        }
        if ($value === '') { // add additional qualifying conditions here only
            unset($array[$key]);
        }
    }

    return $array;
}

var_export(recursivelyRemoveEmpties($raw));

*请注意,此脚本并非设计用于容纳数据有效负载中的对象。

array_filter() and empty() may be safe to leverage for the asker's sample input, but they are not reliable for public general use. These native functions will treat all "falsey" values as filterable/empty. See the documentation for empty() for details on its greedy determination of emptiness.

I recommend explicitly checking (data type specifically) for empty string strings if that is the intent. This way you don't inadvertently destroy meaningful data. I am choosing to declare $value as a reference to avoid iterating a copy of the array -- this allows me to mutate/overwrite array data with $value instead of the more verbose $array[$key] (when not using unset().

Code: (Demo with an assortment of falsey values)

function recursivelyRemoveEmpties(array $array): array
{
    foreach ($array as $key => &$value) {  // modify by reference to affect original array
        if (is_array($value)) {
            $value = recursivelyRemoveEmpties($value);
            if (!$value) {  // if the array is empty
                unset($array[$key]);
            }
            continue;
        }
        if ($value === '') { // add additional qualifying conditions here only
            unset($array[$key]);
        }
    }

    return $array;
}

var_export(recursivelyRemoveEmpties($raw));

*Note that this script is not designed to accommodate objects in the data payload.

水波映月 2024-12-15 16:37:30

我的功能:

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

$nonEmpty = array_filter($raw, 'removeEmptyItems');

My function:

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

$nonEmpty = array_filter($raw, 'removeEmptyItems');
流心雨 2024-12-15 16:37:30

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

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

Simple and elegant solution based on recursive function. Dont liked any solution from the prev. answers. Removes empty sub arrays/sub values:

/**
 * 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);
}
吾性傲以野 2024-12-15 16:37:30

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

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

    return !!$item;
}

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. Short: You'll need to pass it by reference:

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

    return !!$item;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文