Remover elementos vazios da matriz


784

Alguns elementos da minha matriz são cadeias vazias com base no que o usuário enviou. Eu preciso remover esses elementos. Eu tenho isto:

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

Mas isso não funciona. $linksArrayainda possui elementos vazios. Eu também tentei fazê-lo com a empty()função, mas o resultado é o mesmo.


1
Eu pensei que valia a pena mencionar que o código acima não funciona porque unset (...) opera na variável criada pelo loop foreach, não na matriz original que obviamente permanece como era antes do loop.
Salvou

if (! vazio ($ link)) {echo $ link; } isso funciona para mim
Shiplu

Você está mudando um link $ que não é referenciado! use foreach ($ linksArray como $ key => $ link) não definido (linksArray [$ key])
TD_Nijboer 22/03

Respostas:


1548

Como você está lidando com uma série de seqüências de caracteres, você pode simplesmente usar array_filter(), que lida convenientemente com tudo isso para você:

print_r(array_filter($linksArray));

Lembre-se de que, se nenhum retorno de chamada for fornecido , todas as entradas da matriz iguais a FALSE(consulte a conversão para booleano ) serão removidas. Portanto, se você precisar preservar elementos que são '0', por exemplo, sequência exata , precisará de um retorno de chamada personalizado:

// 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_filterdeve remover os elementos vazios. E se a definição de vazio do PHP não for a mesma que a sua definição, você poderá preencher a opção de retorno de chamada com uma função anônima que elimina elementos indesejados. Aparentemente, você deve ter o php 5.3 ou posterior para usar retornos de chamada anônimos. stackoverflow.com/questions/2412299/…
Buttle Butkus

76
cuidado com o array_filter não reindexa os índices da matriz (pode ocorrer um problema no uso da matriz de processos na instrução). Então, envolva tudo com a função array_values.
Michal - wereda-net

8
A resposta está incorreta, porque também removerá falseelementos. ( php.net/manual/en/function.array-filter.php )
pliashkou

5
@ Deji, você tentou imprimir essa matriz antes de filtrá-la? Eu acho que definir aa segunda vez apenas redefine a primeira.
Cullub

5
@Cranio: que já está coberto por outro comentário. Não está incorreto, mas talvez seja mais amplo que seus requisitos. Isso não significa que outras pessoas ainda não achem útil; afinal, se tudo o que você tem são cadeias de caracteres em sua matriz, esta resposta removerá apenas as vazias.
Martijn Pieters

169

Você pode usar array_filterpara remover elementos vazios:

$emptyRemoved = array_filter($linksArray);

Se você tiver (int) 0em sua matriz, poderá usar o seguinte:

$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: Talvez seus elementos não estejam vazios por si só, mas contenham um ou mais espaços ... Você pode usar o seguinte antes de usararray_filter

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

10
Acabei de adicioná-lo à resposta aceita pelo BoltClock, você pode simplesmente fazer array_filter ($ foo, 'strlen') para evitar o problema "0" e remover apenas aqueles com tamanho zero.
AB Carroll

2
@ nezZario: Supondo que você tenha apenas scalaritens em sua matriz, sim. Caso contrário, você não pode fazer isso.
Andrew Moore

2
Usando lambda para php> = 5.3function remove_empty($array) { return array_filter($array, function($value){return !empty($value) || $value === 0;}); }
Viral

1
array_map()fiz a mágica porque eu tinha espaços nessas matrizes vazias!
Prodigy

126

A resposta mais popular sobre esse tópico é absolutamente incorreta.

Considere o seguinte script PHP:

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

Por que é isso? Como uma sequência que contém um único caractere '0' também é avaliada como booleana false, mesmo que não seja uma sequência vazia, ela ainda será filtrada. Isso seria um bug.

Passar a função strlen interna como a função de filtragem funcionará, pois retorna um número inteiro diferente de zero para uma sequência não vazia e um número inteiro zero para uma sequência vazia. Inteiros diferentes de zero sempre avaliam como true quando convertidos em booleano, enquanto que inteiros zero sempre avaliam como false quando convertidos em booleano.

Portanto, a resposta absoluta, definitiva e correta é:

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

3
Acordado. Esta deve ser a resposta aceita, para aqueles cuja matriz contém cordas
mwieczorek

2
Votado. Uma resposta melhor do que muitas outras, no entanto, deve-se notar que a resposta atualmente aceita tecnicamente não está incorreta, pois "vazio" realmente tem um significado especial no PHP. (Alguns valores que se qualificam como "vazio": 0, "", null)
rinogo

5
Eles não estão incorretos, é tudo sobre contexto. Em alguns casos, preservar o valor 0 pode ser importante. Então, por favor, não diga que todo mundo está errado, exceto você
Macr1408

6
Isso interrompe se a matriz contiver outra matriz:strlen() expects parameter 1 to be string, array given
hpaknia 28/10

Você pode dizer que essa também pode ser uma boa abordagem (em vez de dizer que as pessoas estão incorretas) para alcançar as ações desejadas. Basicamente, nem todos os casos são semelhantes. Embora essa abordagem esteja funcionando para o meu caso.
MR_AMDEV

102
$linksArray = array_filter($linksArray);

"Se nenhum retorno de chamada for fornecido, todas as entradas de entrada iguais a FALSE serão removidas." - http://php.net/manual/en/function.array-filter.php


4
Eu também tentei isso depois de pesquisar o problema no Google. Infelizmente, deixa nos elementos em branco para mim.
Will

18
isso também removerá '0'
OIS

2
@ Will: você tem certeza? Ele também remove seqüências de caracteres vazias, eu testei com sucesso isso. Talvez seus valores de entrada contenham espaços e devam ser aparados antes. De acordo com as regras de conversão booleana, a cadeia vazia é avaliada como falsa e, portanto, removida por array_filter.
Acme

52
    $myarray = array_filter($myarray, 'strlen');  //removes null values but leaves "0"
    $myarray = array_filter($myarray);            //removes all null values

strlen também remove false :(
justnorris 03/03

42

Você pode apenas fazer

array_filter($array)

array_filter: "Se nenhum retorno de chamada for fornecido, todas as entradas de entrada iguais a FALSE serão removidas." Isso significa que os elementos com valores NULL, 0, '0', '', FALSE, array () também serão removidos.

A outra opção está fazendo

array_diff($array, array(''))

que removerá elementos com valores NULL '' e FALSE.

Espero que isto ajude :)

ATUALIZAR

Aqui está um exemplo.

$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())

Resumindo:

  • 0 ou '0' removerá 0 e '0'
  • NULL, FALSE ou '' removerá NULL, FALSE e ''

36
foreach($linksArray as $key => $link) 
{ 
    if($link === '') 
    { 
        unset($linksArray[$key]); 
    } 
} 
print_r($linksArray); 

4
Uma solução concisa, legível e segura que não remove falsee 0. Considerando que isso foi postado no mesmo minuto que a resposta aceita (que é insegura e incorreta), só posso supor que seus 8 upvotes em comparação com os 649 da resposta aceita se devam à solução de uma linha.
Rybo111

@ rybo111 - possivelmente, embora usando essa lógica em uma chamada de retorno para array_filter()seria uma abordagem mais limpo do que um foreach()ciclo
Mark Baker

Talvez mais rápido, mas sua solução é a mais legível, o que é importante. Para aqueles que usam sua solução requer trim(), eu recomendariaif(is_string($link) && trim($link) === '')
rybo111

33

Outro liner para remover elementos vazios ("" string vazia) do seu array.

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

Nota: Este código deliberadamente mantém null, 0e falseelementos.


Ou talvez você queira aparar os elementos da matriz primeiro:

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

Nota: Este código também remove nulle falseelementos.


3
Exatamente o que eu precisava, e isso também é compatível com PHPs mais antigos , obrigado! ;-)
Stano 11/07

1
@JohnK Wrong. Para fazer isso exatamente como o usuário deseja o retorno de chamada, é necessário, a menos que você deseje remover zeros de alzo e outros valores de falsey.
Cranio

Oh ... isso é absolutamente adorável. Deve ser o aceito.
Henrik Petterson

20

Em resumo:

Este é o meu código sugerido:

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

Explicação:

Eu acho que o uso array_filteré bom, mas não o suficiente, porque os valores são iguais spacee \n, ... mantêm-se na matriz e isso geralmente é ruim.

Então eu sugiro que você use mistura array_filtere array_map.

array_mapé para aparar, array_filteré para remover valores vazios, strlené para manter o 0valor e array_valuesé para indexar novamente, se necessário.

Amostras:

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

Resultados:

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

Teste on-line:

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



12

A resposta mais votada está errada ou, pelo menos, não é completamente verdadeira, pois o OP está falando apenas de strings em branco. Aqui está uma explicação completa:

O que significa vazio ?

Antes de tudo, devemos concordar com o que significa vazio . Você quer filtrar:

  1. as cadeias vazias única ( "")?
  2. os valores estritamente falsos ? ( $element === false)
  3. os valores falsey ? (ou seja, 0, 0,0, "", "0", NULL, matriz () ...)
  4. o equivalente da empty()função do PHP ?

Como você filtra os valores

Para filtrar apenas cadeias vazias :

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

Para filtrar apenas valores estritamente falsos , você deve usar uma função de retorno de chamada :

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

O retorno de chamada também é útil para qualquer combinação na qual você deseja filtrar os valores "falsey", exceto alguns. (Por exemplo, filtre todos nulle falseetc, deixando apenas 0):

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

O terceiro e o quarto casos são (finalmente para nossos propósitos) equivalentes e, para isso, tudo o que você precisa usar é o padrão:

$filtered = array_filter($originalArray);

2
Se você deseja remover nulle false, mas deixar 0, também pode usar a função interna do php strlencomo retorno de chamada.
Cullub

10

Eu tive que fazer isso para manter um valor de matriz de (string) 0

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

9
$a = array(1, '', '', '', 2, '', 3, 4);
$b = array_values(array_filter($a));

print_r($b)

9

Para matriz multidimensional

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

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

Eu uso o seguinte script para remover elementos vazios de uma matriz

for ($i=0; $i<$count($Array); $i++)
  {
    if (empty($Array[$i])) unset($Array[$i]);
  }

7

Só quero contribuir com uma alternativa para loops ... também abordando lacunas nas chaves ...

No meu caso, eu queria manter as chaves sequenciais da matriz quando a operação estivesse concluída (não apenas números ímpares, que era o que eu estava olhando. Configurar código para procurar apenas chaves ímpares parecia frágil para mim e não favorável ao futuro).

Eu estava procurando por algo mais parecido com isto: http://gotofritz.net/blog/howto/removing-empty-array-elements-php/

A combinação de array_filter e array_slice faz o truque.

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

Não faço ideia de eficiência ou benchmarks, mas funciona.


Eu acho que array_values ​​teria o mesmo resultado que array_slice. Isso parece mais intuitivo em termos de ler o código posteriormente e entender o que está fazendo.
Arlomedia 11/03/2015

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

resultado

1: 5

2: 6



5

Apenas uma linha: atualização (graças a @suther):

$array_without_empty_values = array_filter($array);

não precisa do seu segundo parâmetro: $ clean_array = array_filter ($ dirty_array);
Suther

4

use a array_filterfunção para remover valores vazios:

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

Ele deseja remover cadeias de caracteres em branco , o que não é equivalente a valores vazios.
Cranio

4

Remover elementos vazios da matriz

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

funciona!


3

De acordo com o seu método, você pode capturar esses elementos em outra matriz e usar o seguinte,

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

print_r($new_arr);

1

tente isso ** ** Exemplo

$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
o que é isso? existem muitas outras respostas muito relevantes. O que você está adicionando aqui?
Félix Gagnon-Grenier

consulte a url qual era a pergunta aqui !! / * remover elemento de array vazio * /
Ashish Pathak

1

Eu acho que array_walk é muito mais adequado aqui

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

Resultado:

Array
(
    [0] => name
    [2] => 342
    [3] => 0
    [4] => 0
)
  • Garantimos que os valores vazios sejam removidos, mesmo que o usuário adicione mais de um espaço
  • Também aparamos espaços vazios a partir dos valores válidos

  • Por fim, apenas (null), (Boolean False) e ('') serão considerados strings vazias

Não há Falseproblema em removê-lo, porque o AFAIK não pode enviar valores booleanos.


0

Com esses tipos de coisas, é muito melhor ser explícito sobre o que você deseja ou não.

Isso ajudará o próximo cara a não ser pego de surpresa com o comportamento de array_filter()sem retorno de chamada. Por exemplo, acabei com essa pergunta porque esqueci se array_filter()removeNULL ou não. Perdi tempo quando poderia ter usado a solução abaixo e tive a minha resposta.

Além disso, a lógica é angnóstica de linguagem, no sentido de que o código pode ser copiado para outra linguagem sem ter que entender o comportamento de uma função php como array_filter quando nenhum retorno de chamada é passado.

Na minha solução, é claro à primeira vista o que está acontecendo. Remova uma condicional para manter algo ou adicione uma nova condição para filtrar valores adicionais.

Desconsidere o uso real, array_filter()já que estou apenas transmitindo um retorno de chamada personalizado - você pode prosseguir e extrair isso para sua própria função, se desejar. Estou apenas usando-o como açúcar para um foreachloop.

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

Outro benefício dessa abordagem é que você pode separar os predicados de filtragem em uma função abstrata que filtra um único valor por matriz e cria uma solução compostável.

Veja este exemplo e os comentários embutidos para a saída.

<?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]

Agora você pode criar dinamicamente uma função chamada filterer()using pipe()que aplicará essas funções parcialmente aplicadas a você.

<?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]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.