La fonction de rappel dans array_filter()
ne transmet que les valeurs du tableau, pas les clés.
Si j'ai:
$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
Quel est le meilleur moyen de supprimer toutes les clés dans $my_array
qui ne sont pas dans le tableau $allowed
?
Sortie désirée:
$my_array = array("foo" => 1);
PHP 5.6 a introduit un troisième paramètre à array_filter()
, flag
, que vous pouvez définir à ARRAY_FILTER_USE_KEY
pour filtrer par clé au lieu de valeur:
$my_array = ['foo' => 1, 'hello' => 'world'];
$allowed = ['foo', 'bar'];
$filtered = array_filter(
$my_array,
function ($key) use ($allowed) {
return in_array($key, $allowed);
},
ARRAY_FILTER_USE_KEY
);
Il est clair que ce n’est pas aussi élégant que array_intersect_key($my_array, array_flip($allowed))
, mais qu’il offre la flexibilité supplémentaire d’exécuter un test arbitraire sur la clé, par exemple. $allowed
pourrait contenir des motifs regex au lieu de chaînes simples.
Vous pouvez également utiliser ARRAY_FILTER_USE_BOTH
pour que la valeur et la clé soient transmises à votre fonction de filtrage. Voici un exemple artificiel basé sur le premier, mais notez que je ne recommanderais pas l'encodage des règles de filtrage à l'aide de $allowed
de cette façon:
$my_array = ['foo' => 1, 'bar' => 'baz', 'hello' => 'wld'];
$allowed = ['foo' => true, 'bar' => true, 'hello' => 'world'];
$filtered = array_filter(
$my_array,
function ($val, $key) use ($allowed) { // N.b. $val, $key not $key, $val
return isset($allowed[$key]) && (
$allowed[$key] === true || $allowed[$key] === $val
);
},
ARRAY_FILTER_USE_BOTH
); // ['foo' => 1, 'bar' => 'baz']
Avec array_intersect_key
et array_flip
:
var_dump(array_intersect_key($my_array, array_flip($allowed)));
array(1) {
["foo"]=>
int(1)
}
J'avais besoin de faire la même chose, mais avec un array_filter
plus complexe sur les touches.
Voici comment je l'ai fait, en utilisant une méthode similaire.
// Filter out array elements with keys shorter than 4 characters
$a = array(
0 => "val 0",
"one" => "val one",
"two" => "val two",
"three"=> "val three",
"four" => "val four",
"five" => "val five",
"6" => "val 6"
);
$f = array_filter(array_keys($a), function ($k){ return strlen($k)>=4; });
$b = array_intersect_key($a, array_flip($f));
print_r($b);
Ceci produit le résultat:
Array
(
[three] => val three
[four] => val four
[five] => val five
)
Voici une solution plus flexible utilisant une fermeture:
$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$result = array_flip(array_filter(array_flip($my_array), function ($key) use ($allowed)
{
return in_array($key, $allowed);
}));
var_dump($result);
Les sorties:
array(1) {
'foo' =>
int(1)
}
Donc, dans la fonction, vous pouvez faire d’autres tests spécifiques.
array_filter
Indépendamment de la manière dont j'aime la solution de Vincent au problème de Maček, celui-ci n'utilise pas array_filter
. Si vous veniez d'un moteur de recherche, vous recherchiez peut-être quelque chose comme ceci ( PHP> = 5.3 ):
$array = ['Apple' => 'red', 'pear' => 'green'];
reset($array); // Unimportant here, but make sure your array is reset
$apples = array_filter($array, function($color) use ($&array) {
$key = key($array);
next($array); // advance array pointer
return key($array) === 'Apple';
}
Il passe le tableau que vous filtrez en tant que référence au rappel. Comme array_filter
ne parcourt pas le tableau de manière conventionnelle en augmentant le pointeur interne public, vous devez le faire avancer par vous-même.
Ce qui est important ici, c’est que vous devez vous assurer que votre tableau est réinitialisé, sinon vous pourriez commencer en plein milieu.
Dans PHP> = 5.4 , vous pouvez rendre le rappel encore plus court:
$apples = array_filter($array, function($color) use ($&array) {
return each($array)['key'] === 'Apple';
}
Si vous recherchez une méthode pour filtrer un tableau par une chaîne apparaissant dans des clés, vous pouvez utiliser:
$mArray=array('foo'=>'bar','foo2'=>'bar2','fooToo'=>'bar3','baz'=>'nope');
$mSearch='foo';
$allowed=array_filter(
array_keys($mArray),
function($key) use ($mSearch){
return stristr($key,$mSearch);
});
$mResult=array_intersect_key($mArray,array_flip($allowed));
Le résultat de print_r($mResult)
est
Array ( [foo] => bar [foo2] => bar2 [fooToo] => bar3 )
Une adaptation de cette réponse qui prend en charge les expressions régulières
function array_preg_filter_keys($arr, $regexp) {
$keys = array_keys($arr);
$match = array_filter($keys, function($k) use($regexp) {
return preg_match($regexp, $k) === 1;
});
return array_intersect_key($arr, array_flip($match));
}
$mArray = array('foo'=>'yes', 'foo2'=>'yes', 'FooToo'=>'yes', 'baz'=>'nope');
print_r(array_preg_filter_keys($mArray, "/^foo/i"));
Sortie
Array
(
[foo] => yes
[foo2] => yes
[FooToo] => yes
)
Voici une alternative moins flexible utilisant unset () :
$array = array(
1 => 'one',
2 => 'two',
3 => 'three'
);
$disallowed = array(1,3);
foreach($disallowed as $key){
unset($array[$key]);
}
Le résultat de print_r($array)
étant:
Array
(
[2] => two
)
Cela ne s'applique pas si vous souhaitez conserver les valeurs filter pour une utilisation ultérieure, mais plus ordonnées, si vous êtes certain de ne pas le faire.
À partir de PHP 5.6, vous pouvez utiliser l'indicateur ARRAY_FILTER_USE_KEY
dans array_filter
:
$result = array_filter($my_array, function ($k) use ($allowed) {
return in_array($k, $allowed);
}, ARRAY_FILTER_USE_KEY);
Sinon, vous pouvez utiliser cette fonction ( à partir de TestDummy ):
function filter_array_keys(array $array, $callback)
{
$matchedKeys = array_filter(array_keys($array), $callback);
return array_intersect_key($array, array_flip($matchedKeys));
}
$result = filter_array_keys($my_array, function ($k) use ($allowed) {
return in_array($k, $allowed);
});
Et voici une version augmentée de la mienne, qui accepte un rappel ou directement les clés:
function filter_array_keys(array $array, $keys)
{
if (is_callable($keys)) {
$keys = array_filter(array_keys($array), $keys);
}
return array_intersect_key($array, array_flip($keys));
}
// using a callback, like array_filter:
$result = filter_array_keys($my_array, function ($k) use ($allowed) {
return in_array($k, $allowed);
});
// or, if you already have the keys:
$result = filter_array_keys($my_array, $allowed));
Enfin, vous pouvez également utiliser un simple foreach
:
$result = [];
foreach ($my_array as $key => $value) {
if (in_array($key, $allowed)) {
$result[$key] = $value;
}
}
Peut-être une surcharge si vous en avez besoin une seule fois, mais vous pouvez utiliser YaLinqo library * pour filtrer les collections (et effectuer toute autre transformation). Cette bibliothèque permet de réaliser des requêtes de type SQL sur des objets avec une syntaxe fluide. Sa fonction where
accepte un calback avec deux arguments: une valeur et une clé. Par exemple:
$filtered = from($array)
->where(function ($v, $k) use ($allowed) {
return in_array($k, $allowed);
})
->toArray();
(La fonction where
renvoie un itérateur. Par conséquent, si vous devez uniquement effectuer une itération avec foreach
sur la séquence résultante, vous pouvez supprimer ->toArray()
.)
* développé par moi
fonction de filtre de tableau de php:
array_filter ( $array, $callback_function, $flag )
$ array - C'est le tableau d'entrée
$ callback_function - La fonction de rappel à utiliser , Si la fonction de rappel retourne true , la valeur actuelle de array est renvoyée dans le tableau de résultats.
$ flag - C'est paramètre facultatif , il déterminera quels arguments seront envoyés à la fonction de rappel. Si ce paramètre est vide, la fonction de rappel utilisera les valeurs du tableau en tant qu'argument. Si vous voulez envoyer une clé de tableau en tant qu'argument, utilisez $ flag comme ARRAY_FILTER_USE_KEY . Si vous voulez envoyer les clés et les valeurs, vous devez utiliser $ flag comme ARRAY_FILTER_USE_BOTH .
Par exemple: considérons un tableau simple
$array = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
Si vous voulez filtrer un tableau en fonction de la clé array , vous devez utiliser ARRAY_FILTER_USE_KEY as third paramètre de la fonction array array_filter.
$get_key_res = array_filter($array,"get_key",ARRAY_FILTER_USE_KEY );
Si vous souhaitez filtrer un tableau en fonction de la clé et de la valeur du tableau , vous devez utiliser ARRAY_FILTER_USE_BOTH comme troisième paramètre de la fonction de tableau array_filter.
$get_both = array_filter($array,"get_both",ARRAY_FILTER_USE_BOTH );
Exemples de fonctions de rappel:
function get_key($key)
{
if($key == 'a')
{
return true;
} else {
return false;
}
}
function get_both($val,$key)
{
if($key == 'a' && $val == 1)
{
return true;
} else {
return false;
}
}
Il va sortir
Output of $get_key is :Array ( [a] => 1 )
Output of $get_both is :Array ( [a] => 1 )
Avec cette fonction, vous pouvez filtrer un tableau multidimensionnel
function filter_array_keys($array,$filter_keys=array()){
$l=array(&$array);
$c=1;
//This first loop will loop until the count var is stable//
for($r=0;$r<$c;$r++){
//This loop will loop thru the child element list//
$keys = array_keys($l[$r]);
for($z=0;$z<count($l[$r]);$z++){
$object = &$l[$r][$keys[$z]];
if(is_array($object)){
$i=0;
$keys_on_array=array_keys($object);
$object=array_filter($object,function($el) use(&$i,$keys_on_array,$filter_keys){
$key = $keys_on_array[$i];
$i++;
if(in_array($key,$filter_keys) || is_int($key))return false;
return true;
});
}
if(is_array($l[$r][$keys[$z]])){
$l[] = &$l[$r][$keys[$z]];
$c++;
}//IF
}//FOR
}//FOR
return $l[0];
}
// Filtre les éléments du tableau avec des clés de moins de 4 caractères // En utilisant la fonction Anonymous avec Closure ...
function comparison($min)
{
return function($item) use ($min) {
return strlen($item) >= $min;
};
}
$input = array(
0 => "val 0",
"one" => "val one",
"two" => "val two",
"three"=> "val three",
"four" => "val four",
"five" => "val five",
"6" => "val 6"
);
$ output = array_filter (array_keys ($ input), Comparison (4));