После array_filter (), как я могу сбросить ключи, чтобы они шли в числовом порядке, начиная с 0

108

Я просто использовал array_filter для удаления записей, которые имели только значение '' из массива, и теперь я хочу применить к нему определенные преобразования в зависимости от заполнителя, начиная с 0, но, к сожалению, он по-прежнему сохраняет исходный индекс. Некоторое время я искал и ничего не увидел, возможно, я просто упустил очевидное, но мой вопрос ...

Как я могу легко сбросить индексы массива, чтобы они начинались с 0 и переходили по порядку в НОВЫЙ массив, вместо того, чтобы сохранять старые индексы?

jel402
источник
Возможный дубликат php array_filter без сохранения ключей
Yep_It's_Me
Если вы не абсолютно уверены, что в вашем массиве нет пустых / нулевых / ложных значений, я должен убедить вас не использовать их array_filter()- вы можете очистить больше, чем намереваетесь. Вот некоторые объяснения с демонстрацией: stackoverflow.com/a/43657056/2943403
mickmackusa

Ответы:

224

Если вы array_valuesвызовете свой массив, он будет переиндексирован с нуля.

Даниэль Вандерслуис
источник
Ссылка больше не работает, используйте вместо нее php.net/manual/en/function.array-values.php . Я не могу его обновить, так как мне нужно изменить как минимум 6 символов.
Расмус Хансен
37

Если вы используете фильтр Array, сделайте это следующим образом

$NewArray = array_values(array_filter($OldArray));
user2182143
источник
3
О, время, которое я потерял, пытаясь понять, почему результат json_encode массив отличается от результата json_encode массив array_filtered ... спасибо ТАК МНОГО ...
Джертер
13

Меня беспокоит, сколько программистов невинно скопировали / вставили 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 => '',
)

С помощью моего метода вы получаете повторно проиндексированные ключи, все ненулевые значения и ни одно из нулевых значений. Чистый, портативный и надежный однострочник для всех ваших потребностей в фильтрации нулевого массива. Вот демонстрация .



Точно так же, если вы хотите удалить пустые, ложные и нулевые элементы (с сохранением нулей), эти четыре метода будут работать:

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);
Mickmackusa
источник
2
Если вы напишете, все пойдет не так, как ожидалось array_values(array_filter($arr, function($el) {return $el !== '';}))? Это кажется естественным способом сделать то, о чем спрашивает ОП.
Кейси
1
Да. Я считаю, что разработчикам следует избегать побуждения использовать поведение по умолчанию, array_filter()если только их глубокое знание данных не допускает жадную фильтрацию без побочных эффектов. (Еще одно предостережение: empty()ведет себя таким же образом, а также включает в себя пустой массив в своей жадности.)
mickmackusa
2
Этот ответ отвечает на совершенно другой вопрос, никак не связанный с исходным, ни по форме, ни по форме.
AnrDaemon
1
array_filter()ведет себя точно так же, как и следовало ожидать, исходя из того, что написано в руководстве: php.net/manual/en/function.array-filter.php «Если обратный вызов не предоставлен, все записи массива равны FALSE (см. преобразование в логическое ) будет удален ". И программисты PHP должны быть хорошо осведомлены, что 0, null, false, '' и '0' все оценивают как false при принуждении к логическому.
madsen 05
1
Дело в том, что большинство людей не знают, чего ожидать. Да, я знаю, но многие этого не делают. Я опубликовал этот ответ, чтобы помочь людям, которые не знают.
mickmackusa
12

Использование 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
Эд Мазур
источник