Rimuovere gli elementi dell'array vuoti


784

Alcuni elementi nel mio array sono stringhe vuote in base a ciò che l'utente ha inviato. Devo rimuovere quegli elementi. Ho questo:

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

Ma non funziona $linksArrayha ancora elementi vuoti. Ho anche provato a farlo con la empty()funzione, ma il risultato è lo stesso.


1
Ho pensato che valesse la pena ricordare che il codice sopra non funziona perché unset (...) opera sulla variabile creata dal ciclo foreach, non sull'array originale che ovviamente rimane com'era prima del ciclo.
saveario

if (! empty ($ link)) {echo $ link; } questo funziona per me
Shiplu,

U sta cambiando un $ link che non è referenziato! usa foreach ($ linksArray as $ key => $ link) unset (linksArray [$ key])
TD_Nijboer

Risposte:


1548

Dato che hai a che fare con una serie di stringhe, puoi semplicemente usare array_filter(), che gestisce comodamente tutto questo per te:

print_r(array_filter($linksArray));

Tenere presente che se non viene fornito alcun callback , tutte le voci dell'array uguali a FALSE(vedere la conversione in booleano ) verranno rimosse. Quindi, se è necessario preservare elementi che sono cioè stringhe esatte '0', sarà necessario un callback personalizzato:

// 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_filterdovrebbe rimuovere gli elementi vuoti. E se la definizione di PHP di vuoto non è la stessa della tua definizione, puoi compilare l'opzione di callback con una funzione anonima che elimina elementi indesiderati. Apparentemente devi avere php 5.3 o successivo per usare callback anonimi. stackoverflow.com/questions/2412299/…
Buttle Butkus,

76
attenzione array_filter non reindicizza gli indici dell'array (potrebbe verificarsi un problema nell'uso dell'array dei processi per l'istruzione). Quindi avvolgi tutto con la funzione array_values.
Michal - wereda-net,

8
La risposta non è corretta, perché rimuoverà falseanche gli elementi. ( Php.net/manual/en/function.array-filter.php )
pliashkou

5
@Deji hai provato a stampare quell'array prima di filtrarlo? Penso che al' impostazione della seconda volta reimposti la prima.
Cullub,

5
@Cranio: che è già coperto da un altro commento. Non è errato, ma forse più ampio delle tue esigenze. Ciò non significa che altre persone non possano ancora trovare utile; dopo tutto, se tutto ciò che hai sono stringhe nel tuo array, questa risposta rimuoverà solo quelle vuote.
Martijn Pieters

169

Puoi usare array_filterper rimuovere elementi vuoti:

$emptyRemoved = array_filter($linksArray);

Se si dispone (int) 0nel proprio array, è possibile utilizzare quanto segue:

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

MODIFICA: Forse i tuoi elementi non sono vuoti di per sé ma contengono uno o più spazi ... Puoi usare quanto segue prima dell'usoarray_filter

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

10
L'ho appena aggiunto alla risposta accettata da BoltClock, potresti semplicemente fare array_filter ($ foo, 'strlen') per evitare il problema "0" e rimuovere solo quelli con lunghezza zero.
AB Carroll,

2
@nezZario: Supponendo che tu abbia solo scalaroggetti nel tuo array, sì. Altrimenti, non puoi farlo.
Andrew Moore,

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

1
array_map()ha fatto la magia perché avevo spazi in quelle matrici vuote!
Prodigio

127

La risposta più popolare su questo argomento è assolutamente INCORRETTA.

Considera il seguente script PHP:

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

Perchè è questo? Poiché una stringa contenente un singolo carattere "0" viene valutata come falsa booleana, quindi anche se non è una stringa vuota, verrà comunque filtrata. Sarebbe un bug.

Passando la funzione strlen integrata come funzione di filtro funzionerà, perché restituisce un numero intero diverso da zero per una stringa non vuota e un numero intero zero per una stringa vuota. I numeri interi diversi da zero valutano sempre come veri se convertiti in valori booleani, mentre i numeri interi zero valutano sempre come falsi quando convertiti in valori booleani.

Quindi, la risposta assoluta, definitiva, corretta è:

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

3
Concordato. Questa dovrebbe essere la risposta accettata, per coloro il cui array contiene stringhe
mwieczorek,

2
Upvoted. Una risposta migliore di molte altre, tuttavia va notato che la risposta attualmente accettata non è tecnicamente scorretta poiché "vuoto" ha, in effetti, un significato speciale all'interno di PHP. (Alcuni valori che si qualificano come "vuoto": 0, "", null)
rinogo

5
Non sono errati, si tratta di contesto. In alcuni casi conservare il valore 0 potrebbe essere importante. Quindi, per favore, non dire che tutti hanno torto tranne te
Macr1408,

6
Questo si interrompe se l'array contiene un altro array:strlen() expects parameter 1 to be string, array given
hpaknia,

Puoi dire che questo può anche essere un buon approccio (invece di dire altri errati) per raggiungere le azioni desiderate. In pratica non tutti i casi sono simili. Anche se questo approccio funziona nel mio caso.
MR_AMDEV

102
$linksArray = array_filter($linksArray);

"Se non viene fornito alcun callback, verranno rimosse tutte le voci di input pari a FALSE." - http://php.net/manual/en/function.array-filter.php


4
Ho anche provato questo dopo che Google ha riscontrato il problema. Sfortunatamente, lascia negli elementi vuoti per me.
Will

18
questo rimuoverà anche '0'
OIS

2
@Will: ne sei sicuro? Rimuove anche le stringhe vuote, l'ho testato con successo. Forse i tuoi valori di input contengono spazi e dovrebbero essere tagliati prima. Secondo le regole di conversione booleane, la stringa vuota viene valutata come falsa e quindi rimossa da array_filter.
acme

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

strlen rimuove anche false :(
justnorris

42

Puoi solo fare

array_filter($array)

array_filter: "Se non viene fornito alcun callback, verranno rimosse tutte le voci di input pari a FALSE." Ciò significa che verranno rimossi anche gli elementi con valori NULL, 0, '0', '', FALSE, array ().

L'altra opzione sta facendo

array_diff($array, array(''))

che rimuoverà gli elementi con i valori NULL, '' e FALSE.

Spero che sia di aiuto :)

AGGIORNARE

Ecco un esempio

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

Per riassumere:

  • 0 o "0" rimuoveranno 0 e "0"
  • NULL, FALSE o '' rimuoveranno NULL, FALSE e ''

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

4
Una soluzione concisa, leggibile e sicura che non rimuove falsee 0. Considerando che questo è stato pubblicato nello stesso minuto della risposta accettata (non sicura e errata), posso solo supporre che i tuoi 8 voti positivi rispetto alla risposta accettata 649 dipenda dal fatto che quest'ultima è una soluzione a una riga.
Rybo111,

@ rybo111 - probabilmente, anche se usare quella logica in un callback array_filter()sarebbe un approccio più pulito di un foreach()loop
Mark Baker,

Forse più veloce, ma la tua soluzione è la più leggibile, il che è importante. Per coloro che utilizzano la tua soluzione che richiede trim(), consigliereiif(is_string($link) && trim($link) === '')
rybo111

33

Un altro liner per rimuovere elementi vuoti ("" stringa vuota) dall'array.

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

Nota: Questo codice mantiene volutamente null, 0e falsegli elementi.


O forse vuoi prima tagliare gli elementi dell'array:

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

Nota: questo codice rimuove anche nulled falseelementi.


3
Esattamente quello di cui ho bisogno, e questo è anche compatibile con i vecchi PHP , grazie! ;-)
Stano,

1
@JohnK Wrong. Per fare ciò esattamente come l'utente desidera il callback è necessario, a meno che non si voglia rimuovere gli zero di alzo e altri valori di falsi.
Cranio,

Oh ... questo è assolutamente adorabile. Dovrebbe essere quello accettato.
Henrik Petterson,

20

In breve:

Questo è il mio codice suggerito:

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

Spiegazione:

Penso che l'uso array_filtersia buono, ma non abbastanza, perché i valori sono simili spacee \n, ... mantengono l'array e questo di solito è negativo.

Quindi vi consiglio di usare miscela array_filtere array_map.

array_mapè per il taglio, array_filterè per rimuovere i valori vuoti, strlenè per mantenere il 0valore ed array_valuesè per la reindicizzazione se necessario.

Campioni:

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

risultati:

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

Test online:

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


13

Se si lavora con una matrice numerica e è necessario indicizzare nuovamente la matrice dopo aver rimosso gli elementi vuoti, utilizzare la funzione array_values :

array_values(array_filter($array));

Vedi anche: PHP reindex array?


12

La risposta più votata è sbagliata o almeno non del tutto vera poiché l'OP parla solo di stringhe vuote. Ecco una spiegazione approfondita:

Cosa significa vuoto ?

Prima di tutto, dobbiamo concordare sul significato di vuoto . Intendi filtrare:

  1. le stringhe vuote solo ( "")?
  2. i valori rigorosamente falsi ? ( $element === false)
  3. i valori di falsità ? (ovvero 0, 0.0, "", "0", NULL, array () ...)
  4. l'equivalente della empty()funzione di PHP ?

Come filtrare i valori

Per filtrare solo le stringhe vuote :

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

Per filtrare solo valori strettamente falsi , è necessario utilizzare una funzione di callback :

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

Il callback è utile anche per qualsiasi combinazione in cui si desidera filtrare i valori "false", tranne alcuni. (Ad esempio, filtrare ogni nulle false, ecc., Lasciando solo 0):

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

Il terzo e il quarto caso sono (per i nostri scopi finalmente) equivalenti, e per questo tutto ciò che devi usare è l'impostazione predefinita:

$filtered = array_filter($originalArray);

2
Se vuoi eliminare nulle false, ma lasciare 0, puoi anche usare la funzione integrata di php strlencome callback.
Cullub,

10

Ho dovuto farlo per mantenere un valore di array di (stringa) 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

Per array multidimensionali

$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

Uso il seguente script per rimuovere elementi vuoti da un array

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

7

Voglio solo contribuire con un'alternativa ai loop ... anche per colmare le lacune nei tasti ...

Nel mio caso volevo mantenere le chiavi sequenziali dell'array quando l'operazione era completa (non solo i numeri dispari, che è quello che stavo fissando. L'impostazione del codice per cercare solo le chiavi dispari mi sembrava fragile e non favorevole al futuro.)

Stavo cercando qualcosa di più simile a questo: http://gotofritz.net/blog/howto/removing-empty-array-elements-php/

La combinazione di array_filter e array_slice fa il trucco.

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

Nessuna idea su efficienze o benchmark ma funziona.


Penso che array_values ​​avrebbe lo stesso risultato di array_slice. Ciò sembra più intuitivo in termini di lettura del codice in un secondo momento e comprensione di ciò che sta facendo.
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>';
} 

produzione

1: 5

2: 6



5

Solo una riga: Aggiornamento (grazie a @suther):

$array_without_empty_values = array_filter($array);

non è necessario il secondo parametro: $ clean_array = array_filter ($ dirty_array);
Suther,

4

usa la array_filterfunzione per rimuovere valori vuoti:

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

Vuole rimuovere le stringhe vuote , il che non equivale a valori vuoti.
Cranio,

4

Rimuovere gli elementi dell'array vuoti

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

Funziona!


3

Secondo il tuo metodo, puoi semplicemente prendere quegli elementi in un altro array e usare quello come segue,

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

print_r($new_arr);

1

prova questo ** ** Esempio

$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
cos'è questo? ci sono tonnellate di altre risposte molto rilevanti. Cosa stai aggiungendo qui?
Félix Gagnon-Grenier,

controlla l'url qual era la domanda qui !! / * rimuovi l'elemento array vuoto * /
Ashish pathak

1

Penso che array_walk sia molto più adatto qui

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

Produzione:

Array
(
    [0] => name
    [2] => 342
    [3] => 0
    [4] => 0
)
  • Ci siamo assicurati che i valori vuoti vengano rimossi anche se l'utente aggiunge più di uno spazio
  • Abbiamo anche tagliato gli spazi vuoti dai valori validi

  • Infine, solo (null), (Boolean False) e ('') saranno considerati stringhe vuote

Per quanto riguarda Falseok, rimuoverlo, perché AFAIK l'utente non può inviare valori booleani.


0

Con questi tipi di cose, è molto meglio essere espliciti su ciò che vuoi e non vuoi.

Aiuterà il prossimo a non farsi sorprendere dal comportamento di array_filter()senza callback. Ad esempio, ho finito con questa domanda perché ho dimenticato se array_filter()rimuove NULLo no. Ho perso tempo quando avrei potuto usare la soluzione qui sotto e avere la mia risposta.

Inoltre, la logica è il linguaggio angnostico, nel senso che il codice può essere copiato in un'altra lingua senza dover comprendere il comportamento di una funzione php come array_filterquando non viene passato alcun callback.

Nella mia soluzione, è chiaro a prima vista cosa sta succedendo. Rimuovi un condizionale per conservare qualcosa o aggiungi una nuova condizione per filtrare valori aggiuntivi.

Ignora l'utilizzo effettivo array_filter()dal momento che sto solo passando un callback personalizzato - potresti andare avanti ed estrarlo alla sua stessa funzione se lo desideri. Lo sto solo usando come zucchero per un 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);

Un altro vantaggio di questo approccio è che è possibile suddividere i predicati di filtro in una funzione astratta che filtra un singolo valore per array e crea una soluzione componibile.

Vedi questo esempio e i commenti incorporati per l'output.

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

Ora puoi creare dinamicamente una funzione chiamata filterer()using pipe()che applicherà queste funzioni parzialmente applicate per te.

<?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]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.