Видаліть порожні елементи масиву


783

Деякі елементи в моєму масиві - це порожні рядки на основі того, що користувач подав. Мені потрібно видалити ці елементи. У мене це:

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

Але це не працює. $linksArrayвсе ще є порожні елементи. Я також намагався виконувати цю empty()функцію, але результат той самий.


1
Я подумав, що варто згадати, що наведений вище код не працює, оскільки unset (...) працює на змінній, створеній циклом foreach, а не на оригінальному масиві, який, очевидно, залишається таким, як був до циклу.
врятованеаріо

if (! empty ($ link)) {echo $ link; } це працює для мене
Шиплу

U змінюють посилання $, яке не стосується! використовувати foreach ($ linksArray як $ key => $ link) unset (linksArray [$ key])
TD_Nijboer

Відповіді:


1547

Якщо ви маєте справу з масивом рядків, ви можете просто використовувати 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 !== "";')));

16
array_filterповинні видалити порожні елементи. І якщо визначення PHP порожнім не зовсім збігається з вашим визначенням, ви можете заповнити опцію зворотного виклику анонімною функцією, яка викидає непотрібні елементи. Мабуть, ви повинні мати php 5.3 або пізнішої версії, щоб використовувати анонімні зворотні дзвінки. stackoverflow.com/questions/2412299/…
Buttle Butkus

76
стежте за тим, як array_filter не індексує індекси масиву (може виникнути проблема при використанні масиву процесів для оператора). Тому оберніть все це функцією array_values.
Міхал - wereda-net

8
Відповідь невірна, оскільки вона також видалить falseелементи. ( php.net/manual/en/function.array-filter.php )
pliashkou

5
@Deji Ви спробували надрукувати цей масив перед його фільтруванням? Я думаю, що встановлення aвдруге просто скидає перший.
Cullub

5
@Cranio: який уже охоплений іншим коментарем. Це невірно, але, можливо, ширше, ніж ваші вимоги. Це не означає, що інші люди ще не можуть вважати його корисним; зрештою, якщо у вас у масиві є рядки, ця відповідь видалить лише порожні.
Martijn Pieters

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;
}

EDIT: Можливо, ваші елементи самі по собі не порожні, але містять одне або кілька пробілів ... Перед використанням ви можете скористатись наступнимarray_filter

$trimmedArray = array_map('trim', $linksArray);

10
Я щойно додав його до прийнятої відповіді BoltClock, ви можете просто зробити array_filter ($ foo, 'strlen'), щоб уникнути проблеми "0" і видалити лише ті, що мають нульову довжину.
AB Carroll

2
@nezZario: Якщо припустити, що scalarу вашому масиві є лише елементи. Інакше ви не можете цього зробити.
Ендрю Мур

2
Використання лямбда для php> = 5.3function remove_empty($array) { return array_filter($array, function($value){return !empty($value) || $value === 0;}); }
Вірусний

1
array_map()зробив магію, тому що у мене були пробіли в цих порожніх масивах!
Prodigy

126

Найпопулярніша відповідь на цю тему - абсолютно НЕПРАВИЛЬНА.

Розглянемо наступний сценарій PHP:

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

Чому це? Оскільки рядок, що містить один символ "0", також оцінює булева помилка, тому, хоча це не порожня рядок, вона все одно буде відфільтрована. Це була б помилка.

Передача вбудованої функції strlen як функції фільтрації буде працювати, оскільки вона повертає ненульове ціле число для непустого рядка, а нульове ціле число для порожнього рядка. Ненульові цілі числа завжди оцінюються як істинні при перетворенні в булеві, а нульові цілі цілі завжди оцінюються як хибні, коли перетворюються на булеві.

Отже, абсолютна, остаточна, правильна відповідь:

$arr = array_filter($arr, 'strlen');

3
Домовились. Це має бути прийнятою відповіддю для тих, чий масив містить рядки
mwieczorek

2
Отримано. Краща відповідь, ніж багато інших, однак слід зазначити, що прийнята в даний час відповідь технічно не є хибною, оскільки "порожній" дійсно має особливе значення в 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


4
Я також спробував це після вирішення проблеми Google. На жаль, це залишає для мене порожні елементи.
Буде

18
це також видалить '0'
OIS

2
@Will: ти впевнений? Це також видаляє порожні рядки, я це успішно перевірив. Можливо, ваші вхідні значення містять пробіли, і їх слід обрізати раніше. Відповідно до правил булевого перетворення порожній рядок оцінюється як хибний і тому видаляється array_filter.
акме

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 та ""

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елементи.


3
Саме те, що мені потрібно, і це також сумісне з більш старими PHP , дякую! ;-)
Стано

1
@JohnK Неправильно. Для того, щоб зробити це точно як користувач whants до зворотного виклику буде необхідний, якщо ви не хочете , щоб видалити alzo нулі і інші значення falsey.
Краніо

О ... це абсолютно прекрасно. Повинен бути прийнятим.
Генрік Петтерсон

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-масив reindex?


12

Відповідь, яка найбільше голосує, є неправильною або, принаймні, не зовсім правдивою, оскільки ОП говорить лише про порожні рядки. Ось ґрунтовне пояснення:

Що означає порожнє ?

Перш за все, ми повинні погодитись, що означає порожній . Ви маєте на увазі відфільтрувати:

  1. лише порожні рядки ("")?
  2. в строго помилкові цінності? ( $element === false)
  3. в falsey значення? (тобто 0, 0,0, "", "0", NULL, масив () ...)
  4. еквівалент функції PHP empty()?

Як ви фільтруєте значення

Щоб фільтрувати лише порожні рядки :

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

Щоб відфільтрувати лише суто помилкові значення, потрібно використовувати функцію зворотного виклику :

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

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

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

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

$filtered = array_filter($originalArray);

2
Якщо ви хочете вийняти nullі false, але залишити 0, ви також можете використовувати вбудований phpstrlen функцію як зворотний дзвінок.
Cullub

10

Я повинен був зробити це для того, щоб зберегти значення масиву (string) 0

$url = array_filter($data, function ($value) {
  return (!empty($value) || $value === 0 || $value==='0');
});


9

Для багатовимірного масиву

$data = array_map('array_filter', $data);
$data = array_filter($data);


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);

Немає уявлення про ефективність чи орієнтири, але це працює.


Я думаю, що array_values ​​матиме такий самий результат, як array_slice. Це здається більш інтуїтивним з точки зору читання коду пізніше та розуміння того, що він робить.
арломедія

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

Лише один рядок: оновлення (завдяки @suther):

$array_without_empty_values = array_filter($array);

не потрібен ваш другий параметр: $ clean_array = array_filter ($ dirty_array);
суть

4

використовувати array_filterфункцію для видалення порожніх значень:

$linksArray = array_filter($linksArray);
print_r($linksArray);

Він хоче видалити порожні рядки , що не еквівалентно порожнім значенням.
Краніо

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);

це працює!


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, про що тут було питання !! / * видалити порожній елемент масиву * /
Ashish pathak

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()за допомогою, 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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.