Supprimer les éléments de tableau vides

784

Certains éléments de mon tableau sont des chaînes vides basées sur ce que l'utilisateur a soumis. Je dois supprimer ces éléments. J'ai ceci:

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

Mais ça ne marche pas. $linksArraya encore des éléments vides. J'ai également essayé de le faire avec la empty()fonction, mais le résultat est le même.

Volonté
la source
1
J'ai pensé qu'il valait la peine de mentionner que le code ci-dessus ne fonctionne pas car unset (...) fonctionne sur la variable créée par la boucle foreach, pas sur le tableau d'origine qui reste évidemment tel qu'il était avant la boucle.
saveario
if (! empty ($ link)) {echo $ link; } cela fonctionne pour moi
Shiplu
Vous modifiez un lien $ qui n'est pas référencé! utiliser foreach ($ linksArray as $ key => $ link) unset (linksArray [$ key])
TD_Nijboer

Réponses:

1548

Comme vous avez affaire à un tableau de chaînes, vous pouvez simplement utiliser array_filter()ce qui gère tout cela à votre place:

print_r(array_filter($linksArray));

Gardez à l'esprit que si aucun rappel n'est fourni , toutes les entrées de tableau égales à FALSE(voir conversion en booléen ) seront supprimées. Donc, si vous devez conserver des éléments qui sont par exemple une chaîne exacte '0', vous aurez besoin d'un rappel personnalisé:

// 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
la source
16
array_filterdevrait supprimer les éléments vides. Et si la définition de PHP de vide n'est pas tout à fait la même que votre définition, vous pouvez remplir l'option de rappel avec une fonction anonyme qui rejette les éléments indésirables. Apparemment, vous devez avoir php 5.3 ou version ultérieure pour utiliser les rappels anonymes. stackoverflow.com/questions/2412299/…
Buttle Butkus
76
attention array_filter ne réindexe pas les index de tableau (un problème peut survenir lors de l'utilisation du tableau de processus dans l'instruction for). Enveloppez donc tout cela avec la fonction array_values.
Michal - wereda-net
8
La réponse est incorrecte, car elle supprimera falseégalement les éléments. ( php.net/manual/en/function.array-filter.php )
pliashkou
5
@Deji avez-vous essayé d'imprimer ce tableau avant de le filtrer? Je pense que régler ala deuxième fois réinitialise simplement la première.
Cullub
5
@Cranio: qui est déjà couvert par un autre commentaire. Ce n'est pas incorrect, mais peut-être plus large que vos besoins. Cela ne signifie pas que d'autres personnes ne peuvent toujours pas trouver cela utile; après tout, si vous n'avez que des chaînes dans votre tableau, cette réponse supprimera uniquement les chaînes vides.
Martijn Pieters
169

Vous pouvez utiliser array_filterpour supprimer des éléments vides:

$emptyRemoved = array_filter($linksArray);

Si vous en avez (int) 0dans votre tableau, vous pouvez utiliser ce qui suit:

$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: Peut-être que vos éléments ne sont pas vides en soi mais contiennent un ou plusieurs espaces ... Vous pouvez utiliser ce qui suit avant d'utiliserarray_filter

$trimmedArray = array_map('trim', $linksArray);
Andrew Moore
la source
10
Je viens de l'ajouter à la réponse acceptée par BoltClock, vous pouvez simplement faire array_filter ($ foo, 'strlen') pour éviter le problème "0" et ne supprimer que ceux de longueur nulle.
AB Carroll le
2
@nezZario: En supposant que vous n'avez que des scalaréléments dans votre tableau, oui. Sinon, vous ne pouvez pas faire ça.
Andrew Moore
2
Utilisation de lambda pour php> = 5,3function remove_empty($array) { return array_filter($array, function($value){return !empty($value) || $value === 0;}); }
Viral
1
array_map()a fait le cos magique que j'avais des espaces dans ces tableaux vides!
Prodigy
127

La réponse la plus populaire sur ce sujet est absolument INCORRECTE.

Considérez le script PHP suivant:

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

Pourquoi est-ce? Parce qu'une chaîne contenant un seul caractère «0» est également évaluée comme booléenne false, donc même si ce n'est pas une chaîne vide, elle sera toujours filtrée. Ce serait un bug.

Le passage de la fonction strlen intégrée en tant que fonction de filtrage fonctionnera, car il renvoie un entier non nul pour une chaîne non vide et un entier zéro pour une chaîne vide. Les entiers non nuls sont toujours évalués comme vrais lorsqu'ils sont convertis en booléens, tandis que les entiers nuls sont toujours évalués comme faux lorsqu'ils sont convertis en booléens.

Donc, la réponse absolue, définitive et correcte est:

$arr = array_filter($arr, 'strlen');
Ron Cemer
la source
3
D'accord. Cela devrait être la réponse acceptée, pour ceux dont le tableau contient des chaînes
mwieczorek
2
A voté. Une meilleure réponse que la plupart des autres, mais il convient de noter que la réponse actuellement acceptée n'est techniquement pas incorrecte car "vide" a, en effet, une signification particulière dans PHP. (Certaines valeurs qui se qualifient comme « vide »: 0, "", null)
rinogo
5
Ils ne sont pas incorrects, c'est une question de contexte. Dans certains cas, la préservation de la valeur 0 peut être importante. Alors s'il vous plaît, ne dites pas que tout le monde a tort sauf vous
Macr1408
6
Cela casse si le tableau contient un autre tableau:strlen() expects parameter 1 to be string, array given
hpaknia
Vous pouvez dire que cela peut également être une bonne approche (au lieu de dire que les autres sont incorrects) pour réaliser les actions souhaitées.En gros, tous les cas ne sont pas similaires.
MR_AMDEV
102
$linksArray = array_filter($linksArray);

"Si aucun rappel n'est fourni, toutes les entrées d'entrée égales à FALSE seront supprimées." - http://php.net/manual/en/function.array-filter.php

tamasd
la source
4
J'ai également essayé ceci après avoir résolu le problème avec Google. Malheureusement, cela laisse des éléments vides pour moi.
Will
18
cela supprimera également «0»
OIS
2
@Will: êtes-vous sûr? Il supprime également les chaînes vides, j'ai testé cela avec succès. Peut-être que vos valeurs d'entrée contiennent des espaces et doivent être coupées avant. Selon les règles de conversion booléennes, la chaîne vide est évaluée à false et donc supprimée par 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
la source
strlen supprime également false :(
justnorris
42

Tu peux juste faire

array_filter($array)

array_filter: "Si aucun rappel n'est fourni, toutes les entrées d'entrée égales à FALSE seront supprimées." Cela signifie que les éléments avec les valeurs NULL, 0, '0', '', FALSE, array () seront également supprimés.

L'autre option fait

array_diff($array, array(''))

qui supprimera les éléments avec les valeurs NULL, '' et FALSE.

J'espère que cela t'aides :)

MISE À JOUR

Voici un exemple.

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

Pour résumer:

  • 0 ou '0' supprimera 0 et '0'
  • NULL, FALSE ou '' supprimera NULL, FALSE et ''
helpse
la source
36
foreach($linksArray as $key => $link) 
{ 
    if($link === '') 
    { 
        unset($linksArray[$key]); 
    } 
} 
print_r($linksArray); 
Mark Baker
la source
4
Une solution concise, lisible et sûre qui ne supprime pas falseet 0. Étant donné que cela a été publié la même minute que la réponse acceptée (ce qui est dangereux et incorrect), je ne peux que supposer que vos 8 votes positifs par rapport au 649 de la réponse acceptée sont dus à ce que cette dernière soit une solution à une ligne.
rybo111
@ rybo111 - peut-être, bien que l'utilisation de cette logique dans un rappel array_filter()serait une approche plus propre qu'une foreach()boucle
Mark Baker
Peut-être plus rapidement, mais votre solution est la plus lisible, ce qui est important. Pour ceux qui utilisent votre solution trim(), je recommanderaisif(is_string($link) && trim($link) === '')
rybo111
33

Un autre liner pour supprimer les éléments vides ("" chaîne vide) de votre tableau.

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

Remarque: Ce code maintient délibérément null, 0et des falseéléments.


Ou peut-être souhaitez-vous d'abord couper vos éléments de tableau:

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

Remarque: Ce code supprime également les éléments nullet false.

marcovtwout
la source
3
Exactement ce dont j'avais besoin, et cela est également compatible avec les anciens PHP , merci! ;-)
Stano
1
@JohnK Wrong. Pour ce faire, exactement comme l'utilisateur souhaite que le rappel soit nécessaire, sauf si vous souhaitez supprimer les zéros alzoïques et autres valeurs de falsey.
Cranio
Oh ... c'est absolument charmant. Doit être accepté.
Henrik Petterson
20

En bref:

Voici mon code suggéré:

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

Explication:

Je pense que l'utilisation array_filterest bonne, mais pas suffisante, car les valeurs sont comme spaceet \n, ... gardez dans le tableau et c'est généralement mauvais.

Donc , je vous suggère d' utiliser le mélange array_filteret array_map.

array_mapsert à rogner, array_filterà supprimer les valeurs vides, strlenà conserver la 0valeur et array_valuesà réindexer si vous en avez besoin.

Échantillons:

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

Résultats:

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 en ligne:

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

Nabi KAZ
la source
13

Si vous travaillez avec un tableau numérique et devez réindexer le tableau après avoir supprimé les éléments vides, utilisez la fonction array_values :

array_values(array_filter($array));

Voir aussi: tableau de réindexation PHP?

mulquin
la source
12

La réponse la plus votée est fausse ou du moins pas complètement vraie car l'OP ne parle que de chaînes vides. Voici une explication approfondie:

Que signifie vide ?

Tout d'abord, nous devons convenir de ce que signifie vide . Voulez-vous filtrer:

  1. les chaînes vides uniquement ("")?
  2. les valeurs strictement fausses ? ( $element === false)
  3. les valeurs de falsey ? (ie 0, 0.0, "", "0", NULL, array () ...)
  4. l'équivalent de la empty()fonction de PHP ?

Comment filtrez-vous les valeurs

Pour filtrer uniquement les chaînes vides :

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

Pour filtrer uniquement les valeurs strictement fausses , vous devez utiliser une fonction de rappel :

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

Le rappel est également utile pour toute combinaison dans laquelle vous souhaitez filtrer les valeurs "falsey", à l'exception de certaines. (Par exemple, filtrez chaque nullet false, etc., en laissant uniquement 0):

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

Les troisième et quatrième cas sont (pour nos fins enfin) équivalents, et pour cela tout ce que vous avez à utiliser est la valeur par défaut:

$filtered = array_filter($originalArray);
Cranio
la source
2
Si vous voulez supprimer nullet falselaisser 0, vous pouvez également utiliser la fonction intégrée de php strlencomme rappel.
Cullub
10

Je devais le faire afin de garder une valeur de tableau de (chaîne) 0

$url = array_filter($data, function ($value) {
  return (!empty($value) || $value === 0 || $value==='0');
});
Mat
la source
9
$a = array(1, '', '', '', 2, '', 3, 4);
$b = array_values(array_filter($a));

print_r($b)
user2511140
la source
9

Pour tableau multidimensionnel

$data = array_map('array_filter', $data);
$data = array_filter($data);
HMagdy
la source
9
$out_array = array_filter($input_array, function($item) 
{ 
    return !empty($item['key_of_array_to_check_whether_it_is_empty']); 
}
);
Naitik Shah
la source
9
function trim_array($Array)
{
    foreach ($Array as $value) {
        if(trim($value) === '') {
            $index = array_search($value, $Array);
            unset($Array[$index]);
        }
    }
    return $Array;
}
Ali Farmani
la source
7

J'utilise le script suivant pour supprimer des éléments vides d'un tableau

for ($i=0; $i<$count($Array); $i++)
  {
    if (empty($Array[$i])) unset($Array[$i]);
  }
concept w
la source
7

Je veux juste contribuer à une alternative aux boucles ... combler également les lacunes dans les clés ...

Dans mon cas, je voulais conserver les clés de tableau séquentielles une fois l'opération terminée (pas seulement les nombres impairs, c'est ce que je regardais. La configuration du code pour rechercher uniquement les clés impaires m'a semblé fragile et pas pour l'avenir.)

Je cherchais quelque chose de plus comme ceci: http://gotofritz.net/blog/howto/removing-empty-array-elements-php/

La combinaison de array_filter et array_slice fait l'affaire.

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

Aucune idée sur l'efficacité ou les repères mais ça marche.

Chrisdigital
la source
Je pense que array_values ​​aurait le même résultat que array_slice. Cela semble plus intuitif pour lire le code plus tard et comprendre ce qu'il fait.
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>';
} 

production

1: 5

2: 6

Naitik Shah
la source
5
foreach($arr as $key => $val){
   if (empty($val)) unset($arr[$key];
}
Mak Ashtekar
la source
simple, direct!
Richter
5

Une seule ligne: mise à jour (grâce à @suther):

$array_without_empty_values = array_filter($array);
Mat
la source
n'avez pas besoin de votre deuxième paramètre: $ clean_array = array_filter ($ dirty_array);
2014
4

utilisez la array_filterfonction pour supprimer les valeurs vides:

$linksArray = array_filter($linksArray);
print_r($linksArray);
Ankit Gupta
la source
Il veut supprimer des chaînes vides , ce qui n'est pas équivalent à des valeurs vides.
Cranio
4

Supprimer les éléments de tableau vides

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

Ça marche!

iBet7o
la source
3

Selon votre méthode, vous pouvez simplement attraper ces éléments dans un autre tableau et utiliser celui-ci comme suit,

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

print_r($new_arr);
Shahrukh Anwar
la source
1

essayez ceci ** ** Exemple

$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
la source
1
Qu'est-ce que c'est? il y a des tonnes d'autres réponses très pertinentes. Qu'ajoutez-vous ici?
Félix Gagnon-Grenier
consultez l'url quelle était la question ici !! / * supprimer l'élément de tableau vide * /
Ashish pathak
1

Je pense que array_walk est beaucoup plus approprié ici

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

Production:

Array
(
    [0] => name
    [2] => 342
    [3] => 0
    [4] => 0
)
  • Nous nous sommes assurés que les valeurs vides sont supprimées même si l'utilisateur ajoute plus d'un espace
  • Nous avons également coupé les espaces vides des valeurs valides

  • Enfin, seuls (null), (Boolean False) et ('') seront considérés comme des chaînes vides

Pour Falsece qui est de la supprimer, car AFAIK, l'utilisateur ne peut pas soumettre de valeurs booléennes.

Pluie
la source
0

Avec ce genre de choses, il vaut mieux être explicite sur ce que vous voulez et ce que vous ne voulez pas.

Cela aidera le prochain gars à ne pas se laisser surprendre par le comportement de array_filter()sans rappel. Par exemple, je me suis retrouvé sur cette question car j'ai oublié si array_filter()supprime NULLou non. J'ai perdu du temps alors que j'aurais pu utiliser la solution ci-dessous et avoir ma réponse.

De plus, la logique est un langage angnostique dans le sens où le code peut être copié dans un autre langage sans avoir à comprendre le comportement d'une fonction php comme array_filterquand aucun rappel n'est passé.

Dans ma solution, il est clair au regard de ce qui se passe. Supprimez une condition pour conserver quelque chose ou ajoutez une nouvelle condition pour filtrer des valeurs supplémentaires.

Ne tenez pas compte de l'utilisation réelle de array_filter()car je ne fais que lui faire un rappel personnalisé - vous pouvez continuer et l'extraire dans sa propre fonction si vous le souhaitez. Je l'utilise juste comme sucre pour une foreachboucle.

<?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 autre avantage de cette approche est que vous pouvez séparer les prédicats de filtrage en une fonction abstraite qui filtre une seule valeur par tableau et créer une solution composable.

Voir cet exemple et les commentaires en ligne pour la sortie.

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

Vous pouvez maintenant créer dynamiquement une fonction appelée filterer()using pipe()qui appliquera ces fonctions partiellement appliquées pour vous.

<?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
la source