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 NULL
ou 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_filter
quand 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 foreach
boucle.
<?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]