Удалить пустые элементы массива

784

Некоторые элементы в моем массиве являются пустыми строками, основанными на том, что отправил пользователь. Мне нужно удалить эти элементы. У меня есть это:

foreach($linksArray as $link)
{
    if($link == '')
    {
        unset($link);
    }
}
print_r($linksArray);

Но это не работает. $linksArrayвсе еще имеет пустые элементы. Я также пытался сделать это с помощью empty()функции, но результат тот же.

Будет
источник
1
Я подумал, что стоит упомянуть, что приведенный выше код не работает, потому что unset (...) работает с переменной, созданной циклом foreach, а не с исходным массивом, который, очевидно, остается таким, каким он был до цикла.
спасарио
if (! empty ($ link)) {echo $ link; } это работает для меня
Шиплу
Вы меняете ссылку на $, на которую нет ссылок! использовать foreach ($ linksArray как $ key => $ link) unset (linksArray [$ key])
TD_Nijboer

Ответы:

1550

Поскольку вы имеете дело с массивом строк, вы можете просто использовать array_filter(), что удобно для вас:

print_r(array_filter($linksArray));

Имейте в виду, что если обратный вызов не предоставлен , все записи массива, равные FALSE(см. Преобразование в логическое значение ), будут удалены. Поэтому, если вам нужно сохранить элементы, которые являются точной строкой '0', вам понадобится специальный обратный вызов:

// PHP 7.4 and later
print_r(array_filter($linksArray, fn($value) => !is_null($value) && $value !== ''));

// PHP 5.3 and later
print_r(array_filter($linksArray, function($value) { return !is_null($value) && $value !== ''; }));

// PHP < 5.3
print_r(array_filter($linksArray, create_function('$value', 'return $value !== "";')));
BoltClock
источник
16
array_filterследует удалить пустые элементы. И если в PHP определение empty не совпадает с вашим определением, вы можете заполнить опцию обратного вызова анонимной функцией, которая выбрасывает нежелательные элементы. Очевидно, у вас должен быть php 5.3 или более поздней версии, чтобы использовать анонимные обратные вызовы. stackoverflow.com/questions/2412299/…
Баттл Буткус
76
Осторожно, array_filter не переиндексирует индексы массива (может возникнуть проблема при использовании массива процессов в операторе for). Так что оберните все это с помощью функции array_values.
Михал - wereda-нет
8
Ответ неправильный, потому что он также удалит falseэлементы. ( php.net/manual/en/function.array-filter.php )
плиашкоу
5
@ Деджи, ты пытался распечатать этот массив перед его фильтрацией? Я думаю, что установка aвторого раза просто сбрасывает первый.
Cullub
5
@Cranio: который уже покрыт другим комментарием. Это не неправильно, но, возможно, шире, чем ваши требования. Это не значит, что другие люди не могут найти это полезным до сих пор; в конце концов, если у вас есть только строки в вашем массиве, этот ответ удалит только пустые.
Мартин Питерс
169

Вы можете использовать array_filterдля удаления пустых элементов:

$emptyRemoved = array_filter($linksArray);

Если у вас есть (int) 0в вашем массиве, вы можете использовать следующее:

$emptyRemoved = remove_empty($linksArray);

function remove_empty($array) {
  return array_filter($array, '_remove_empty_internal');
}

function _remove_empty_internal($value) {
  return !empty($value) || $value === 0;
}

РЕДАКТИРОВАТЬ: Может быть, ваши элементы не пустые как таковые, но содержат один или несколько пробелов ... Вы можете использовать следующее перед использованиемarray_filter

$trimmedArray = array_map('trim', $linksArray);
Эндрю Мур
источник
10
Я просто добавил его к принятому ответу BoltClock, вы можете просто сделать array_filter ($ foo, 'strlen'), чтобы избежать проблемы "0" и удалить только те, которые имеют нулевую длину.
А.Б. Кэрролл
2
@nezZario: если у вас есть только scalarэлементы в вашем массиве, да. В противном случае вы не можете этого сделать.
Эндрю Мур
2
Использование лямбды для php> = 5.3function remove_empty($array) { return array_filter($array, function($value){return !empty($value) || $value === 0;}); }
Viral
1
array_map()сделал магию, потому что у меня были пробелы в этих пустых массивах!
Prodigy
127

Самый популярный ответ на эту тему абсолютно НЕПРАВИЛЬНЫЙ.

Рассмотрим следующий PHP-скрипт:

<?php
$arr = array('1', '', '2', '3', '0');
// Incorrect:
print_r(array_filter($arr));
// Correct:
print_r(array_filter($arr, 'strlen'));

Почему это? Поскольку строка, содержащая один символ «0», также имеет логическое значение false, поэтому, даже если она не является пустой строкой, она все равно будет отфильтрована. Это было бы ошибкой.

Передача встроенной функции strlen в качестве функции фильтрации будет работать, потому что она возвращает ненулевое целое число для непустой строки и нулевое целое число для пустой строки. Ненулевые целые всегда оцениваются в true при преобразовании в логическое значение, в то время как нулевые целые всегда оцениваются в false при преобразовании в логическое значение.

Итак, абсолютный, окончательный, правильный ответ:

$arr = array_filter($arr, 'strlen');
Рон Кемер
источник
3
Согласовано. Это должен быть принятый ответ для тех, чей массив содержит строки
mwieczorek
2
Upvoted. Лучший ответ, чем многие другие, однако следует отметить, что принятый в настоящее время ответ технически не является неправильным, поскольку «пустой» действительно имеет особое значение в PHP. (Некоторые значения , которые квалифицируются как "пустые": 0, "", null)
rinogo
5
Они не неправильные, все дело в контексте. В некоторых случаях сохранение значения 0 может быть важным. Поэтому, пожалуйста, не говорите, что все неправы, кроме вас
Macr1408
6
Это ломается, если массив содержит другой массив:strlen() expects parameter 1 to be string, array given
hpaknia
Вы можете сказать, что это также может быть хорошим подходом (вместо того, чтобы говорить, что другие неверны) для достижения желаемых действий. В основном, не все случаи одинаковы. Хотя этот подход работает для моего случая.
MR_AMDEV
102
$linksArray = array_filter($linksArray);

«Если обратный вызов не предоставлен, все записи ввода, равные FALSE, будут удалены». - http://php.net/manual/en/function.array-filter.php

tamasd
источник
4
Я также попробовал это после того, как Google столкнулся с проблемой. К сожалению, это оставляет в пустых элементах для меня.
Будет
18
это также удалит '0'
OIS
2
@Will: ты уверен? Удаляет также пустые строки, я успешно проверил это. Возможно, ваши входные значения содержат пробелы и должны быть обрезаны до. Согласно логическим правилам преобразования, пустая строка оценивается как ложная и, следовательно, удаляется array_filter.
Acme
52
    $myarray = array_filter($myarray, 'strlen');  //removes null values but leaves "0"
    $myarray = array_filter($myarray);            //removes all null values
матия канчижан
источник
strlen также удаляет false :(
justnorris
42

Вы можете просто сделать

array_filter($array)

array_filter: «Если обратный вызов не предоставлен, все записи ввода, равные FALSE, будут удалены». Это означает, что элементы со значениями NULL, 0, '0', '', FALSE, array () также будут удалены.

Другой вариант делает

array_diff($array, array(''))

который удалит элементы со значениями NULL, '' и FALSE.

Надеюсь это поможет :)

ОБНОВИТЬ

Вот пример.

$a = array(0, '0', NULL, FALSE, '', array());

var_dump(array_filter($a));
// array()

var_dump(array_diff($a, array(0))) // 0 / '0'
// array(NULL, FALSE, '', array());

var_dump(array_diff($a, array(NULL))) // NULL / FALSE / ''
// array(0, '0', array())

Подводить итоги:

  • 0 или «0» удалит 0 и «0»
  • NULL, FALSE или '' удалит NULL, FALSE и ''
helpse
источник
36
foreach($linksArray as $key => $link) 
{ 
    if($link === '') 
    { 
        unset($linksArray[$key]); 
    } 
} 
print_r($linksArray); 
Марк Бейкер
источник
4
Краткое, читаемое и безопасное решение, которое не удаляет falseи 0. Учитывая, что это было опубликовано в ту же минуту, что и принятый ответ (это небезопасно и неверно), я могу только предположить, что ваши 8 голосов проголосовали по сравнению с принятым ответом 649, а последний - решение в одну строку.
rybo111
@ rybo111 - возможно, хотя использование этой логики в обратном вызове array_filter()было бы более чистым подходом, чем foreach()цикл
Марк Бейкер
Возможно, быстрее, но ваше решение является наиболее читабельным, что важно. Для тех, кто использует ваше решение trim(), я бы порекомендовалif(is_string($link) && trim($link) === '')
rybo111
33

Еще один вкладыш для удаления пустых ("" пустых строк) элементов из вашего массива.

$array = array_filter($array, function($a) {return $a !== "";});

Примечание: Этот код намеренно держит null, 0и falseэлементы.


Или, может быть, вы хотите сначала обрезать элементы массива:

$array = array_filter($array, function($a) {
    return trim($a) !== "";
});

Примечание: этот код также удаляет nullи falseэлементы.

marcovtwout
источник
3
Именно то, что мне нужно, и это также совместимо со старыми PHP , спасибо! ;-)
Стано
1
@JohnK Неправильно. Для того, чтобы сделать это точно как пользователь whants до обратного вызова будет необходим, если вы не хотите , чтобы удалить alzo нули и другие значения falsey.
Cranio
Ох ... это очень мило. Должен быть принятым.
Хенрик Петтерсон
20

Короче говоря:

Это мой предложенный код:

$myarray =  array_values(array_filter(array_map('trim', $myarray), 'strlen'));

Объяснение:

Я думаю, что использование array_filterэто хорошо, но не достаточно, потому что значения будут как spaceи \n... держать в массиве, и это обычно плохо.

Поэтому я предлагаю вам использовать смесь array_filterи array_map.

array_mapпредназначен для обрезки, array_filterдля удаления пустых значений, strlenдля сохранения 0значения и array_valuesдля повторной индексации, если вам нужно.

Образцы:

$myarray = array("\r", "\n", "\r\n", "", " ", "0", "a");

// "\r", "\n", "\r\n", " ", "a"
$new1 = array_filter($myarray);

// "a"
$new2 = array_filter(array_map('trim', $myarray));

// "0", "a"
$new3 = array_filter(array_map('trim', $myarray), 'strlen');

// "0", "a" (reindex)
$new4 = array_values(array_filter(array_map('trim', $myarray), 'strlen'));

var_dump($new1, $new2, $new3, $new4);

Результаты:

array(5) {
  [0]=>
" string(1) "
  [1]=>
  string(1) "
"
  [2]=>
  string(2) "
"
  [4]=>
  string(1) " "
  [6]=>
  string(1) "a"
}
array(1) {
  [6]=>
  string(1) "a"
}
array(2) {
  [5]=>
  string(1) "0"
  [6]=>
  string(1) "a"
}
array(2) {
  [0]=>
  string(1) "0"
  [1]=>
  string(1) "a"
}

Онлайн тест:

http://phpio.net/s/5yg0

Наби КАЗ
источник
13

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

array_values(array_filter($array));

Также см .: PHP переиндексировать массив?

mulquin
источник
12

Ответ с наибольшим количеством голосов является неправильным или, по крайней мере, не совсем верным, поскольку ОП говорит только о пустых строках. Вот подробное объяснение:

Что значит пустое ?

Прежде всего, мы должны договориться о том, что означает пустое . Вы хотите отфильтровать:

  1. только пустые строки ("")?
  2. в строго ложные ценности? ( $element === false)
  3. в falsey значения? (т. е. 0, 0.0, "", "0", NULL, array () ...)
  4. эквивалент функции PHP empty()?

Как вы фильтруете значения

Чтобы отфильтровать только пустые строки :

$filtered = array_diff($originalArray, array(""));

Чтобы отфильтровывать только строго ложные значения, вы должны использовать функцию обратного вызова :

$filtered = array_diff($originalArray, 'myCallback');
function myCallback($var) {
    return $var === false;
}

Обратный вызов также полезен для любой комбинации, в которой вы хотите отфильтровать значения "falsey", кроме некоторых. (Например, отфильтруйте каждый nullи falseт. Д., Оставив только 0):

$filtered = array_filter($originalArray, 'myCallback');
function myCallback($var) {
    return ($var === 0 || $var === '0');
}

Третий и четвертый случай (для наших целей наконец) эквивалентны, и для этого все, что вам нужно использовать, это значение по умолчанию:

$filtered = array_filter($originalArray);
черепно
источник
2
Если вы хотите удалить nullи false, но оставить 0, вы также можете использовать встроенную strlenфункцию php в качестве обратного вызова.
Cullub
10

Я должен был сделать это, чтобы сохранить значение массива (строка) 0

$url = array_filter($data, function ($value) {
  return (!empty($value) || $value === 0 || $value==='0');
});
Matt
источник
9
$a = array(1, '', '', '', 2, '', 3, 4);
$b = array_values(array_filter($a));

print_r($b)
user2511140
источник
9

Для многомерного массива

$data = array_map('array_filter', $data);
$data = array_filter($data);
HMagdy
источник
9
$out_array = array_filter($input_array, function($item) 
{ 
    return !empty($item['key_of_array_to_check_whether_it_is_empty']); 
}
);
Наитик Шах
источник
9
function trim_array($Array)
{
    foreach ($Array as $value) {
        if(trim($value) === '') {
            $index = array_search($value, $Array);
            unset($Array[$index]);
        }
    }
    return $Array;
}
Али Фармани
источник
7

Я использую следующий скрипт для удаления пустых элементов из массива

for ($i=0; $i<$count($Array); $i++)
  {
    if (empty($Array[$i])) unset($Array[$i]);
  }
концепция ж
источник
7

Просто хочу внести альтернативу циклам ... также устранить пробелы в ключах ...

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

Я искал что-то более похожее на это: http://gotofritz.net/blog/howto/removing-empty-array-elements-php/

Комбинация array_filter и array_slice делает свое дело.

$example = array_filter($example); $example = array_slice($example,0);

Никаких идей по эффективности или контрольным показателям, но это работает.

Chrisdigital
источник
Я думаю, что array_values ​​будет иметь тот же результат, что и array_slice. Это кажется более интуитивным с точки зрения чтения кода позже и понимания того, что он делает.
arlomedia
6
$my = ("0"=>" ","1"=>"5","2"=>"6","3"=>" ");   

foreach ($my as $key => $value) {
    if (is_null($value)) unset($my[$key]);
}

foreach ($my as $key => $value) {
    echo   $key . ':' . $value . '<br>';
} 

вывод

1: 5

2: 6

Наитик Шах
источник
5
foreach($arr as $key => $val){
   if (empty($val)) unset($arr[$key];
}
Мак Аштекар
источник
просто, прямо!
Рихтер
5

Всего одна строка: обновление (спасибо @suther):

$array_without_empty_values = array_filter($array);
Matt
источник
вам не нужен ваш второй параметр: $ clean_array = array_filter ($ dirty_array);
Süther
4

используйте array_filterфункцию для удаления пустых значений:

$linksArray = array_filter($linksArray);
print_r($linksArray);
Анкит Гупта
источник
Он хочет удалить пустые строки , что не эквивалентно пустым значениям.
Cranio
4

Удалить пустые элементы массива

function removeEmptyElements(&$element)
{
    if (is_array($element)) {
        if ($key = key($element)) {
            $element[$key] = array_filter($element);
        }

        if (count($element) != count($element, COUNT_RECURSIVE)) {
            $element = array_filter(current($element), __FUNCTION__);
        }

        return $element;
    } else {
        return empty($element) ? false : $element;
    }
}

$data = array(
    'horarios' => array(),
    'grupos' => array(
        '1A' => array(
            'Juan' => array(
                'calificaciones' => array(
                    'Matematicas' => 8,
                    'Español' => 5,
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => 20,
                    'febrero' => 10,
                    'marzo' => '',
                )
            ),
            'Damian' => array(
                'calificaciones' => array(
                    'Matematicas' => 10,
                    'Español' => '',
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => 20,
                    'febrero' => '',
                    'marzo' => 5,
                )
            ),
        ),
        '1B' => array(
            'Mariana' => array(
                'calificaciones' => array(
                    'Matematicas' => null,
                    'Español' => 7,
                    'Ingles' => 9,
                ),
                'asistencias' => array(
                    'enero' => null,
                    'febrero' => 5,
                    'marzo' => 5,
                )
            ),
        ),
    )
);

$data = array_filter($data, 'removeEmptyElements');
var_dump($data);

оно работает!

iBet7o
источник
3

Согласно вашему методу, вы можете просто перехватить эти элементы в другом массиве и использовать его следующим образом:

foreach($linksArray as $link){
   if(!empty($link)){
      $new_arr[] = $link
   }
}

print_r($new_arr);
Шахрух Анвар
источник
1

попробуйте это ** ** Пример

$or = array(
        'PersonalInformation.first_name' => $this->request->data['User']['first_name'],
        'PersonalInformation.last_name' => $this->request->data['User']['last_name'],
        'PersonalInformation.primary_phone' => $this->request->data['User']['primary_phone'],
        'PersonalInformation.dob' => $this->request->data['User']['dob'],
        'User.email' => $this->request->data['User']['email'],
    );



 $or = array_filter($or);

    $condition = array(
        'User.role' => array('U', 'P'),
        'User.user_status' => array('active', 'lead', 'inactive'),
        'OR' => $or
    );
Ашиш Патхак
источник
1
что это? Есть множество других очень важных ответов. Что вы добавляете сюда?
Феликс Ганьон-Гренье,
посмотрите URL-адрес, что здесь за вопрос !! / * удалить пустой элемент массива * /
Ашиш Патхак
1

Я думаю, что array_walk гораздо более подходит здесь

$linksArray = array('name', '        ', '  342', '0', 0.0, null, '', false);

array_walk($linksArray, function(&$v, $k) use (&$linksArray){
    $v = trim($v);
    if ($v == '')
        unset($linksArray[$k]);
});
print_r($linksArray);

Вывод:

Array
(
    [0] => name
    [2] => 342
    [3] => 0
    [4] => 0
)
  • Мы убедились, что пустые значения удаляются, даже если пользователь добавляет более одного пробела
  • Мы также урезали пустые места из допустимых значений

  • Наконец, только (null), (Boolean False) и ('') будут считаться пустыми строками

Что касается Falseего нормально, потому что AFAIK пользователь не может отправлять логические значения.

дождь
источник
0

С такими вещами гораздо лучше быть откровенным о том, что вы хотите, а чего не хотите.

Это поможет следующему парню не быть застигнутым врасплох поведением array_filter()без обратного вызова. Например, я остановился на этом вопросе, потому что я забыл, array_filter()удаляет NULLили нет. Я потратил впустую время, когда я мог только использовать решение ниже и иметь мой ответ.

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

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

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

<?php

$xs = [0, 1, 2, 3, "0", "", false, null];

$xs = array_filter($xs, function($x) {
    if ($x === null) { return false; }
    if ($x === false) { return false; }
    if ($x === "") { return false; }
    if ($x === "0") { return false; }
    return true;
});

$xs = array_values($xs); // reindex array   

echo "<pre>";
var_export($xs);

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

Посмотрите этот пример и встроенные комментарии для вывода.

<?php

/**
 * @param string $valueToFilter
 *
 * @return \Closure A function that expects a 1d array and returns an array
 *                  filtered of values matching $valueToFilter.
 */
function filterValue($valueToFilter)
{
    return function($xs) use ($valueToFilter) {
        return array_filter($xs, function($x) use ($valueToFilter) {
            return $x !== $valueToFilter;
        });
    };
}

// partially applied functions that each expect a 1d array of values
$filterNull = filterValue(null);
$filterFalse = filterValue(false);
$filterZeroString = filterValue("0");
$filterEmptyString = filterValue("");

$xs = [0, 1, 2, 3, null, false, "0", ""];

$xs = $filterNull($xs);        //=> [0, 1, 2, 3, false, "0", ""]
$xs = $filterFalse($xs);       //=> [0, 1, 2, 3, "0", ""]
$xs = $filterZeroString($xs);  //=> [0, 1, 2, 3, ""]
$xs = $filterEmptyString($xs); //=> [0, 1, 2, 3]

echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]

Теперь вы можете динамически создавать функцию filterer()с помощью using, pipe()которая будет применять эти частично примененные функции для вас.

<?php

/**
 * Supply between 1..n functions each with an arity of 1 (that is, accepts
 * one and only one argument). Versions prior to php 5.6 do not have the
 * variadic operator `...` and as such require the use of `func_get_args()` to
 * obtain the comma-delimited list of expressions provided via the argument
 * list on function call.
 *
 * Example - Call the function `pipe()` like:
 *
 *   pipe ($addOne, $multiplyByTwo);
 *
 * @return closure
 */
function pipe()
{
    $functions = func_get_args(); // an array of callable functions [$addOne, $multiplyByTwo]
    return function ($initialAccumulator) use ($functions) { // return a function with an arity of 1
        return array_reduce( // chain the supplied `$arg` value through each function in the list of functions
            $functions, // an array of functions to reduce over the supplied `$arg` value
            function ($accumulator, $currFn) { // the reducer (a reducing function)
                return $currFn($accumulator);
            },
            $initialAccumulator
        );
    };
}

/**
 * @param string $valueToFilter
 *
 * @return \Closure A function that expects a 1d array and returns an array
 *                  filtered of values matching $valueToFilter.
 */
function filterValue($valueToFilter)
{
    return function($xs) use ($valueToFilter) {
        return array_filter($xs, function($x) use ($valueToFilter) {
            return $x !== $valueToFilter;
        });
    };
}

$filterer = pipe(
    filterValue(null),
    filterValue(false),
    filterValue("0"),
    filterValue("")
);

$xs = [0, 1, 2, 3, null, false, "0", ""];
$xs = $filterer($xs);

echo "<pre>";
var_export($xs); //=> [0, 1, 2, 3]
Puiu
источник