Как удалить пустые значения из многомерного массива в PHP?

Я искал много ответов, но ни один из них не работает для меня.

Это данные, назначенные моему массиву $quantities:

Array(
    [10] => Array([25.00] => 1)
    [9] => Array([30.00] => 3)
    [8] => Array([30.00] => 4)
    [12] => Array([35.00] => )
    [1] => Array([30.00] => )
    [2] => Array([30.00] => )
)

Я ищу способ удалить подмассивы с пустыми значениями, такими как [12] [1] и [2], сохраняя при этом все остальное.

Желаемый результат:

Array(
    [10] => Array([25.00] => 1)
    [9] => Array([30.00] => 3)
    [8] => Array([30.00] => 4)
)

Я пробовал множество функций в официальной документации по php, и ни одна из них не работала.

Я использовал этот:

function array_filter_recursive($array, $callback = null) {
    foreach ($array as $key => & $value) {
        if (is_array($value)) {
            $value = array_filter_recursive($value, $callback);
        } else {
            if ( ! is_null($callback)) {
                if ( ! $callback($value)) {
                    unset($array[$key]);
                }
            } else {
                if ( ! (bool) $value) {
                    unset($array[$key]);
                }
            }
        }
    }
    unset($value);
    return $array;
}

Но он удаляет только элемент в подмассивах; Мне нужно полностью удалить подмассивы.

Я не хочу этого:

Array(
    [10] => Array([25.00] => 1)
    [9] => Array([30.00] => 3)
    [8] => Array([30.00] => 4)
    [12] => Array()
    [1] => Array()
    [2] => Array()
)

person Richard-MX    schedule 18.04.2012    source источник
comment
Попробуйте вместо этого использовать var_dump(), чтобы показать нам содержимое массива.   -  person Ja͢ck    schedule 14.05.2013
comment
Для страницы, которая используется в качестве места назначения для такого количества ссылок-обманок, на этой странице есть невероятное количество неправильных ответов, за которые проголосовали. @Richard-MX Я опубликовал ответ, в котором не используются рекурсия или множественные итерационные функции, чтобы читатели, которые попали сюда, могли увидеть экономичное (нулевое) безопасное решение. (в вашем сообщении неясно, имеют ли ваши пустые массивы пустые строки или null в качестве значений, поэтому я демонстрировал оба)   -  person mickmackusa    schedule 15.10.2017


Ответы (8)


Немного поздно, но может помочь кому-то, кто ищет тот же ответ. Я использовал этот очень простой подход к;

  1. удалить все ключи из вложенных массивов, которые не содержат значения, затем
  2. удалить все пустые вложенные массивы.

$postArr = array_map('array_filter', $postArr);
$postArr = array_filter( $postArr );
person Alastair F    schedule 13.09.2013

В моем случае работала следующая функция. Мы можем использовать простую рекурсивную функцию для удаления всех пустых элементов из многомерного массива PHP:

function array_filter_recursive($input){
    foreach ($input as &$value){
        if (is_array($value)){
            $value = array_filter_recursive($value);
        }
    }
    return array_filter($input);
}

Тогда нам просто нужно вызвать эту функцию:

$myArray = array_filter_recursive($myArray);
person Reza Mamun    schedule 03.09.2015

Не уверен, что это именно то, что вы ищете. <удар>

function array_remove_null($array) {
    foreach ($array as $key => $value)
    {
        if(is_null($value))
            unset($array[$key]);
        if(is_array($value))
            $array[$key] = array_remove_null($value);
    }
    return $array;
}

Обновление (исправления):

function array_remove_null($array) {
    foreach ($array as $key => $value)
    {
        if(is_null($value))
            unset($array[$key]);
        if(is_string($value) && empty($value))
            unset($array[$key]);
        if(is_array($value))
            $array[$key] = array_remove_null($value);
        if(isset($array[$key]) && count($array[$key])==0)
            unset($array[$key]);
    }
    return $array;
}

Я уверен, что лучше проверить и сделать это более надежным, может помочь решению.

person Jason Foglia    schedule 18.04.2012
comment
Привет Джейсон, спасибо за ваш ответ. К сожалению, это не работает для того, что мне нужно. Как ответ Пола, он возвращает то же самое, что и исходный вопрос. - person Richard-MX; 18.04.2012
comment
Я не уверен, почему у этого есть 4 голоса. Этот ответ только для кода не работает. Демо - person mickmackusa; 15.10.2017
comment
@micmackusa этот пример работал еще во времена PHP 5. - person Jason Foglia; 16.10.2017
comment
@JasonFoglia Нет никакой конкретной версии, которая повлияла бы на ваш ответ. В php5 тоже не работает. Демонстрация PHP 5.5.0.a.2 - person mickmackusa; 17.10.2017
comment
@micmackusa Этот ответ отвечает на вопрос. Как удалить ЗНАЧЕНИЯ из массива; не пустые массивы из массивов. - person Jason Foglia; 17.10.2017
comment
Давайте продолжим обсуждение в чате. - person Jason Foglia; 17.10.2017

используйте array_map() для фильтрации каждого массива в массиве $:

$newArray = array_map('array_filter', $array);

Вот демонстрация

person Naitik Shah    schedule 11.09.2014
comment
Этот ответ НЕ РАБОТАЕТ. Это не работает в опубликованной демо-ссылке. Это не работает в моей демо-ссылке Как это заработало 3 голоса? Минус от меня. - person mickmackusa; 15.10.2017

$newArray = array_map('array_filter', $array);

Этот синтаксис - это работа и очень помогает, ребята, спасибо.

person Jakfar Shodiq    schedule 13.11.2014
comment
Это точный дублирующий метод (символ за символом) ответа НайтикШаха, который был опубликован двумя месяцами ранее. Если вы не можете улучшить свой ответ, чтобы предоставить более точную информацию, вы должны удалить этот ответ, потому что он не добавляет ценности странице (это просто раздувание страницы). - person mickmackusa; 15.10.2017
comment
Этот ответ НЕ РАБОТАЕТ. Это не работает в моей демо-ссылке Как это заработало 3 голоса? Минус от меня. - person mickmackusa; 15.10.2017

Используйте array_filter с array_map, как показано ниже:

$arr=array_filter(array_map('array_filter', $arr));
person lalithkumar    schedule 24.05.2017
comment
Это не новая информация. Это дубликат ответа AlastairF, написанный в виде одной строки. - person mickmackusa; 17.10.2017

Это рекурсивно удаляет все элементы с нулевыми значениями в многомерных массивах. Работает на PHP >= 5.6. Если вы хотите удалить все «пустые» значения, замените !is_null($value) на !empty($value).

function recursivelyRemoveItemsWithNullValuesFromArray(array $data = []): array
{
    $data = array_map(function($value) {
        return is_array($value) ? recursivelyRemoveItemsWithNullValuesFromArray($value) : $value;
    }, $data);

    return array_filter($data, function($value) {
        return !is_null($value);
    });
}
person HKandulla    schedule 08.06.2017
comment
Этот ответ не дает желаемого результата OP. Демо - person mickmackusa; 18.10.2017
comment
@micmackusa Как указано в моем ответе, если вы хотите удалить все пустые значения, замените !is_null($value) на !empty($value). You Demo работает, как и ожидалось. Я обновил вашу демонстрацию, используя empty() вместо is_null(). Пожалуйста, проверьте: sandbox.onlinephpfunctions.com/code/ - person HKandulla; 02.08.2019

Поскольку подмассивы в вашем массиве содержат только один элемент, вы можете упростить этот подход, используя любой из двух следующих методов. Логическое преимущество заключается в том, чтобы избежать функционального итератора (array_filter) на элементах второго уровня. Вот почему current() больше подходит для этого вопроса/страницы.

Код: (Демо)

$quantities=[
    10=>['25.00'=>1],
    9=>['30.00'=>3],
    8=>['30.00'=>4],
    12=>['35.00'=>null],
    1=>['30.00'=>''],
    2=>['30.00'=>null]
];

var_export(array_filter($quantities,function($a){return strlen(current($a));}));

OR

foreach($quantities as $key=>$sub){  // could be done "by reference" but that impacts code stability
    if(!strlen(current($sub))){  // if subarray value has no length
        unset($quantities[$key]);
    }
}
var_export($quantities);

Оба выводят один и тот же результат (который намеренно удаляет пустые значения и сохраняет значения 0)

array (
  10 => 
  array (
    '25.00' => 1,
  ),
  9 => 
  array (
    '30.00' => 3,
  ),
  8 => 
  array (
    '30.00' => 4,
  ),
)

В приведенных выше методах strlen() используется для проверки элементов 2-го уровня, потому что OP перечисляет только целые числа как «непустые» значения. У будущих читателей SO могут быть другие требования, основанные на элементах, которые могут содержать false, null, '0', 0 и т. д. Подходящими функциями замены для strlen() могут быть: любая из функции "is_", empty(), любая из функций "ctype" и многое другое.

Если массив 2-го уровня OP содержал более одного элемента, И OP хотел удалить все нулевые, ложные, пустые, нулевые элементы (это означает, что нули не нужны или гарантированно не встречаются), тогда ответ Аластера Ф. был бы лучшим выбором.

Если входной массив OP имел неизвестное количество уровней И элементы с нулевым/ложным-y/пустым/нулевым значением должны быть удалены, то Reza Ответ Мамуна — это логический, рекурсивный подход.

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

person mickmackusa    schedule 15.10.2017