在使用array_filter()函数之后,如何重置数组键,并按照数字顺序从0开始排序?

158

我刚刚使用了array_filter从数组中删除了只有''值的条目,现在我想根据从0开始的占位符对其应用某些转换,但不幸的是,它仍然保留原始索引。我找了一会儿也没有看到任何东西,也许我只是错过了显而易见的事情,但我的问题是...

如何轻松地重置数组的索引,使其从0开始并按顺序排列在新数组中,而不是保留旧索引?


可能是php array_filter without key preservation的重复问题。 - Yep_It's_Me
除非您绝对确定数组中没有任何空/零/假值,否则我必须敦促您不要使用array_filter() - 您可能会清除更多内容。这里有一些解释和演示:https://dev59.com/7nE85IYBdhLWcg3wr1ux#43657056 - mickmackusa
4个回答

318
如果您对数组调用 array_values,它将从零重新索引。

3
链接已失效,请使用http://php.net/manual/en/function.array-values.php替代。我无法更新它,因为我至少需要更改6个字符。 - Rasmus Hansen

67

如果您正在使用数组过滤,请按照以下方式进行操作

$NewArray = array_values(array_filter($OldArray));

17

使用array_values()函数:

<?php

$array = array('foo', 'bar', 'baz');
$array = array_filter($array, function ($var) {
    return $var !== 'bar';
});

print_r($array); // indexes 0 and 2
print_r(array_values($array)); // indexes 0 and 1

17

我担心有多少程序员无意中复制粘贴了array_values(array_filter())方法到他们的代码中——我想知道由于array_filter的贪婪性,有多少程序员不知情地遇到了问题。或者更糟糕的是,有多少人从未发现该函数从数组中清除了太多值......

我将提供一个更好的替代方案来处理从数组中删除NULL元素并重新索引键的这个两步过程。

但是首先,我非常重要地强调array_filter()的贪婪性以及它可能在您的项目中默默地破坏它。以下是一个包含混合值的数组,它将暴露问题:

$array=['foo',NULL,'bar',0,false,null,'0',''];

无论字母大小写如何,空值都将被移除。

但是当我们使用 array_values()array_filter() 后,数组中剩下了什么:

array_values(array_filter($array));

输出数组 ($array):

array (
  0 => 'foo',
  1 => 'bar'
)
// All empty, zero-ish, falsey values were removed too!!!

现在看看使用我的方法,使用array_walk()is_null()生成一个新的过滤后的数组你会得到什么:

array_walk($array,function($v)use(&$filtered){if(!is_null($v)){$filtered[]=$v;}});
这可以分多行书写,以便更易读/解释:
array_walk(                      // iterate each element of an input array
    $array,                      // this is the input array
    function($v)use(&$filtered){ // $v is each value, $filter (output) is declared/modifiable
        if(!is_null($v)){        // this literally checks for null values
            $filtered[]=$v;      // value is pushed into output with new indexes
        }
    }
);

输出数组 ($filter):

array (
  0 => 'foo',
  1 => 'bar',
  2 => 0,
  3 => false,
  4 => '0',
  5 => '',
)

使用我的方法,您可以获得重新索引的键、所有非null值和没有null值。这是一个干净、易于移植和可靠的单行代码,适用于所有的数组空值过滤需求。这里有一个演示



同样地,如果您想要删除空、false和null元素(保留零),这四种方法都可以工作:

var_export(array_values(array_diff($array,[''])));

或者

var_export(array_values(array_diff($array,[null])));
或者
var_export(array_values(array_diff($array,[false])));
或者
var_export(array_values(array_filter($array,'strlen')));

输出:

array (
  0 => 'foo',
  1 => 'bar',
  2 => 0,
  3 => '0',
)

最后,对于那些更喜欢语言结构语法的人,您也可以将符合条件的值推入新数组中以发出新索引。


$array=['foo', NULL, 'bar', 0, false, null, '0', ''];

$result = [];
foreach ($array as $value) {
    if (strlen($value)) {
        $result[] = $value;
    }
}

var_export($result);

3
如果你写成array_values(array_filter($arr, function($el) {return $el !== '';})),事情不就会如预期一样吗?这似乎是实现OP所询问的自然方式。 - Casey
1
是的。我的观点是开发人员应该避免使用 array_filter() 的默认行为,除非他们对数据有深入了解,可以进行贪心过滤而不会产生副作用。(进一步提醒:empty() 也以相同方式表现,并且在其贪心中包括一个空数组。) - mickmackusa
5
这个回复完全回答了一个不同的问题,与原来的问题没有任何关系。 - AnrDaemon
这个答案完全完成了所要求的任务“在过滤数组后重新索引数组”。我还提醒了array_filter(),这很相关,因为谷歌搜索结果可能会将搜索“reindex after array_filter”的研究人员引导到这里。我的答案确实提供了几种实现所需结果的方法,这证明了这个答案是合适/相关的。如果您仍然不满意,我现在可以添加一种语言结构的替代方案。 - mickmackusa
5
array_filter()函数的行为与手册上所说的一样:http://php.net/manual/en/function.array-filter.php “如果没有提供回调函数,则将删除等于FALSE(参见转换为布尔值)的数组中的所有条目。” PHP程序员应该知道,0、null、false、''和'0'在强制转换为布尔值时都会被视为false。 - madsen
1
事实是,大多数人不知道该期望什么。你知道,我知道,但很多人不知道。我发布了这个答案来帮助那些不知道的人。 - mickmackusa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接