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.

Vai
fonte
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 !== "";')));
BoltClock
fonte
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);
Andrew Moore
fonte
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');
Ron Cemer
fonte
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

tamasd
fonte
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
matija kancijan
fonte
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 ''
ajudar
fonte
36
foreach($linksArray as $key => $link) 
{ 
    if($link === '') 
    { 
        unset($linksArray[$key]); 
    } 
} 
print_r($linksArray); 
Mark Baker
fonte
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.

marcovtwout
fonte
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

Nabi KAZ
fonte
13

Se você estiver trabalhando com uma matriz numérica e precisar reindexá -la após remover elementos vazios, use a função array_values :

array_values(array_filter($array));

Veja também: PHP reindex array?

mulquin
fonte
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);
Cranio
fonte
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');
});
Matt
fonte
9
$a = array(1, '', '', '', 2, '', 3, 4);
$b = array_values(array_filter($a));

print_r($b)
user2511140
fonte
9

Para matriz multidimensional

$data = array_map('array_filter', $data);
$data = array_filter($data);
HMagdy
fonte
9
$out_array = array_filter($input_array, function($item) 
{ 
    return !empty($item['key_of_array_to_check_whether_it_is_empty']); 
}
);
Naitik Shah
fonte
9
function trim_array($Array)
{
    foreach ($Array as $value) {
        if(trim($value) === '') {
            $index = array_search($value, $Array);
            unset($Array[$index]);
        }
    }
    return $Array;
}
Ali Farmani
fonte
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]);
  }
conceito w
fonte
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.

Chrisdigital
fonte
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

Naitik Shah
fonte
5
foreach($arr as $key => $val){
   if (empty($val)) unset($arr[$key];
}
Mak Ashtekar
fonte
simples, direto!
Richter
5

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

$array_without_empty_values = array_filter($array);
Matt
fonte
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);
Ankit Gupta
fonte
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!

iBet7o
fonte
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);
Shahrukh Anwar
fonte
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
    );
Ashish pathak
fonte
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.

Chuva
fonte
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]
puiu
fonte