Фильтр для удаления начальных нулей из числового массива в php

Я хочу создать функцию обратного вызова для удаления из числового массива заданных значений.

Учитывая этот массив: [ 0, 0, 0, 0, 1, 0, 3, 4, 5, 2, 0, ]; Я хочу создать вызываемую функцию для передачи в array_filter, которая будет возвращать этот массив: [1, 0, 3, 4, 5, 2, 0, ];. В этом ответе я видел использование array_filter: Удаление элемента из массива в PHP, но это не совсем то, что мне нужно, потому что этот параметр удалит все 0 из массива, и мне нужно сохранить те, которые не являются ведущий.

Я создал эту функцию, которая циклически обрабатывает массив и возвращает ожидаемый массив, но я хочу использовать что-то более эффективное:

function removeLeading( int $array_values[], $to_remove = 0 )
{
    $is_leading = true;
    $result = [];
    foreach( $array_values as $value ) {
        if ( ( $value == $to_remove ) && ( $is_leading == true ) ) {
            // Do nothing because it is a leading $to_remove
        }
        else {
            $result[] = $value;
            $is_leading = false;
        }
    }
    return $result;
}

Кстати, «завершающий» здесь неправильное слово — оно относится к элементам в конце массива; элементы в начале массива можно назвать «ведущими»

IMSoP 25.06.2024 17:28

Как вы относитесь к хакерским решениям? str_split(preg_replace('/0{2,}/', '', implode('', [ 0, 0, 0, 0, 1, 0, 3, 4, 5, 2, 0, ])))) (Также предполагается, что все значения являются однозначными целыми числами, 10 и т. д. может привести к ошибке)

user3783243 25.06.2024 17:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
5
82
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Тогда вместо того, чтобы копировать оставшиеся элементы на выход один за другим, вы можете использовать array_slice для создания нового массива, начиная с определенного смещения.

$firstElementToKeep = 0;
foreach ( $input as $value ) {
   // As soon as we find a non-zero element, stop looking
   if ( $value !== 0 ) {
      break;
   }
   // Track the offset we reach
   $firstElementToKeep++;
}
$output = array_slice($input, $firstElementToKeep);

При вводе примера в вашем вопросе $firstElementToKeep достигает 4, который является индексом 1, поэтому мы «разрезаем» оттуда до конца массива и получаем желаемый результат.

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

Привет, спасибо, отличный ответ. Мне было интересно, есть ли способ избежать использования цикла. (Я знаю, что в конце концов за кортеном всегда будет цикл), но вы знаете, когда вы делаете подобные вещи, вы используете регулярное выражение, тем не менее ваш ответ отлично справляется с задачей

Tales 25.06.2024 18:05

@Tales Единственная возможная оптимизация, которую я вижу, — это вернуть исходный массив, если $firstElementToKeep равно 0.

Olivier 25.06.2024 18:12

@Tales Как вы говорите, где-то внизу будет цикл, по крайней мере, до тех пор, пока вы используете структуру данных высокого уровня, такую ​​​​как массив PHP, а не находите какой-то сумасшедший трюк, специфичный для процессора, с необработанной памятью. Использование чего-то вроде array_filter переместит цикл на C, но за счет многократного переключения обратно на контекст PHP для запуска обратного вызова, что, вероятно, приведет к чистому снижению производительности. Я не могу не подчеркнуть, что это почти наверняка ненужная микрооптимизация, поэтому более важно иметь код, который легко понять (а регулярные выражения, как известно, не так!)

IMSoP 25.06.2024 18:28

Да, вы можете сделать это с помощью фильтра массива. Хитрость заключается в том, чтобы накопить первые значения и вернуть false, если оно все еще равно нулю.

Это будет работать только в том случае, если вы хотите обрезать ложное значение.

$filtered = array_filter(
    [0, 0, 0, 0, 1, 0, 3, 4, 5, 2, 0],
    function($value) use (&$sum) { return $sum += $value === 0 ? false : $value; }
);

дает тебе

array (
  4 => 1,
  5 => 0,
  6 => 3,
  7 => 4,
  8 => 5,
  9 => 2,
  10 => 0,
)

Но если вы хотите избавиться от исходных индексов, используйте

$filtered = [...array_filter(
    [0, 0, 0, 0, 1, 0, 3, 4, 5, 2, 0],
    function($value) use (&$sum) { return $sum += $value === 0 ? false : $value; }
)];

переиндексировать и сделать так

array (
  0 => 1,
  1 => 0,
  2 => 3,
  3 => 4,
  4 => 5,
  5 => 2,
  6 => 0,
)
Сплатпаковка более лаконична, но менее производительна, чем вызов array_values().
mickmackusa 26.06.2024 00:03

@micmackusa Игра изменилась с выходом PHP 8.x. См. пример ответа: 3v4l.org/N8hNN PHP научился оптимизировать его посредством вызова функции.

Markus Zeller 26.06.2024 09:00

Похоже, что упаковка пятен постоянно ухудшается до версии 8.3.

mickmackusa 26.06.2024 09:22

@mickmackusa Поправьте меня, если я ошибаюсь. На мой взгляд, с версии 8.3 упаковка спадов происходит быстрее, чем array_values. Я интерпретирую меньшую продолжительность как лучшую. ibb.co/3zfZGhz

Markus Zeller 26.06.2024 09:35

Я не думаю, что мы расходимся во мнениях. Разница в производительности незначительна с версии 8.3.

mickmackusa 26.06.2024 09:53

Другие вопросы по теме