web-dev-qa-db-fra.com

PHP: Comment utiliser array_filter () pour filtrer les clés d'un tableau?

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);
312
maček

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']
233
Richard Turner

Avec array_intersect_key et array_flip :

var_dump(array_intersect_key($my_array, array_flip($allowed)));

array(1) {
  ["foo"]=>
  int(1)
}
425
Vincent Savard

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
)
39
Christopher

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.

8
COil

Comment obtenir la clé actuelle d'un tableau en utilisant 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';
}
4
flu

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
)
4
Nicolas Zimmer

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.

3
Alastair

À 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;
    }
}
3
Gras Double

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

1
Athari

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 ) 
0
prince jose

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

}
0
user1220713

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

print_r ($ sortie);
 enter image description here

0
ZOB