La función de devolución de llamada en array_filter() sólo pasa en la matriz de los valores, no las llaves.

Si tengo:

$my_array = array("foo" => 1, "hello" => "world");

$allowed = array("foo", "bar");

¿Cuál es la mejor manera de eliminar todas las claves de $my_array que no están en el $allowed matriz?

De salida deseada:

$my_array = array("foo" => 1);
  • No es una solución, pero el otro enfoque que podría ser útil es para $b = ['foo' => $a['foo'], 'bar' => $a['bar']] Esto resultará en $b['bar'] ser null.
InformationsquelleAutor maček | 2010-11-23

13 Comentarios

  1. 264

    PHP 5.6, introdujo un tercer parámetro para array_filter(), indicador, que se puede establecer para ARRAY_FILTER_USE_KEY filtrar por clave, en lugar de valor:

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

    Claramente esto no es tan elegante como array_intersect_key($mi_matriz, array_flip($permitidas)), pero no ofrecen la flexibilidad adicional de la realización de una arbitraria de la prueba en contra de la clave, por ejemplo, $allowed podría contener patrones de regex en lugar de las cadenas simples.

    También puede utilizar ARRAY_FILTER_USE_BOTH tener el valor y la tecla se pasa a la función de filtro. He aquí un ejemplo inventado basado en la primera, pero se nota que no me había recomendamos la codificación de las reglas de filtrado usando $allowed de esta manera:

    $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']
    • Maldita sea, como el autor de esa característica a la que me debería haber buscado a esta pregunta 😉
    • Gracias, esto es mejor que array_intersect
  2. 441

    Con array_intersect_key y array_flip:

    var_dump(array_intersect_key($my_array, array_flip($allowed)));
    
    array(1) {
      ["foo"]=>
      int(1)
    }
    • Tengo curiosidad por ver si esto es más eficiente que mi solución, aunque? Es definitivamente más elegante 🙂
    • Esta no es una solución, ya que obligaría a que cada valor es único. Edit: lo siento.. no entendí la solución. Voltear en el permitido claves es una buena solución (+1)
    • No sé si es más eficiente, TBH. @konforce : no estoy seguro de entender tu punto. No puede ser que hay dos claves idénticas en una matriz, por lo que sólo se devuelven las llaves en $mi_matriz que están presentes en $permitidos.
    • sí, leí mal tu solución. Mi edición no debe haber sido visible aún cuando respondió.
    • En general, he encontrado que estos tipos de funciones de la matriz son más rápidos que el equivalente foreach bucle (y a veces con mucho), pero la única manera de saber con certeza es el tiempo, tanto en los mismos datos.
    • tiene un punto. Cuando usted mueve de un tirón y los valores son los mismos, sólo el último valor se mantendrá en la matriz. array('foo' => 1, 'bar' => 1) eliminará foo. Usted tendría que usar array_keys lugar.
    • Creo que confundas mi solución. Estoy volteando $permitidos, no $mi_matriz.
    • oh mi. sí, de hecho. Me preguntaba por qué konforce dijo que leyó mal pero no veo facepalm lo siento 🙂
    • O simplemente utilizar ARRAY_FILTER_USE_KEY 😛
    • ¿Por qué utilizar array_flip? Basta con definir el $allowed con las teclas: allowed = array ( 'foo' => 1, 'bar' => 1 );
    • Este no debe ser el más upvoted respuesta, la aceptó respuesta es la manera correcta de ir (por supuesto, si usted está usando php>=5.6)

  3. 39

    Que necesitaba para hacer lo mismo, pero con un más complejo array_filter en las teclas.

    Aquí es como yo lo hice, usando un método similar.

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

    Esta salida es el resultado:

    Array
    (
        [three] => val three
        [four] => val four
        [five] => val five
    )
  4. 8

    Aquí es una solución más flexible el uso de un cierre:

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

    Salidas:

    array(1) {
      'foo' =>
      int(1)
    }

    De modo en la función, usted puede hacer otras pruebas específicas.

    • No me llama exactamente este «más flexible»; se siente mucho menos sencilla que la aceptación de la solución, también.
    • Estoy de acuerdo. Sería más flexible es la condición era más complejo.
    • De paso, para otros usuarios: Esta solución no tratar el caso de que el $mi_matriz tiene valores duplicados o valores que no son números enteros o cadenas de caracteres. Así que no quiero utilizar esta solución.
    • Estoy de acuerdo en que esto es más flexible ya que permite cambiar el filtro de la lógica. Para el ejemplo he utilizado una matriz de desestimar las teclas y devuelta !in_array($clave, $no permitido).
  5. 4

    Si usted está buscando un método para filtrar una matriz por una cadena que se producen en las teclas, se puede utilizar:

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

    El resultado de print_r($mResult) es

    Array ( [foo] => bar [foo2] => bar2 [fooToo] => bar3 )

    Una adaptación de esta respuesta que admite expresiones regulares

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

    Salida

    Array
    (
        [foo] => yes
        [foo2] => yes
        [FooToo] => yes
    )
    • gracias por tu respuesta. Yo diría que el uso de stristr dentro de la «obra» de la función es hacer algunas suposiciones para el usuario final. Tal vez sería mejor permitir que el usuario pase en una expresión regular; esto les daría más flexibilidad sobre ciertas cosas como los anclajes, los límites de la palabra, y el caso de la sensibilidad, etc.
    • He añadido una adaptación de su respuesta, de que podría ayudar a otras personas
    • Usted está en lo cierto, maček, que es una opción más versátil enfoque para los usuarios que se sienten cómodos con regex. Gracias.
  6. 4

    Cómo obtener la clave actual de una matriz cuando se utiliza array_filter

    Independientemente de cómo me gusta Vicente solución para Maček del problema, que en realidad no los uso array_filter. Si usted vino aquí a partir de un motor de búsqueda que usted tal vez donde buscando algo como esto (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';
    }

    Pasa a la matriz filtra como una referencia a la devolución de llamada. Como array_filter no convencionalmente iterar a través de la matriz por el aumento del público puntero interno que tienes que avanzar por sí mismo.

    Lo importante aquí es que usted necesita para asegurarse de que su matriz es cero, de lo contrario usted puede comenzar a la derecha en el medio de ella.

    En PHP >= 5.4 usted podría hacer la devolución de llamada más breve aún:

    $apples = array_filter($array, function($color) use ($&array) {
      return each($array)['key'] === 'apple';
    }
  7. 3

    Aquí es menos flexible alternativa mediante unset():

    $array = array(
        1 => 'one',
        2 => 'two',
        3 => 'three'
    );
    $disallowed = array(1,3);
    foreach($disallowed as $key){
        unset($array[$key]);
    }

    El resultado de print_r($array) ser:

    Array
    (
        [2] => two
    )

    No es aplicable si se desea mantener la filtrada valores para su posterior uso, pero más ordenado, si estás seguro de que no.

    • Usted debe comprobar si la tecla de $clave existe en $matriz antes de hacer unset.
    • usted no necesita para comprobar si una matriz clave existe cuando se utiliza unset(). No se emiten advertencias si la clave no existe.
  8. 3

    A partir de PHP 5.6, puede utilizar el ARRAY_FILTER_USE_KEY bandera en array_filter:

    $result = array_filter($my_array, function ($k) use ($allowed) {
        return in_array($k, $allowed);
    }, ARRAY_FILTER_USE_KEY);


    De lo contrario, puede utilizar esta función (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);
    });


    Y aquí es una versión aumentada de la mía, que acepta una devolución de llamada o directamente las teclas:

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


    Por último, pero no menos importante, también se puede utilizar una simple foreach:

    $result = [];
    foreach ($my_array as $key => $value) {
        if (in_array($key, $allowed)) {
            $result[$key] = $value;
        }
    }
  9. 1

    Tal vez una exageración si usted necesita sólo una vez, pero se puede usar YaLinqo biblioteca* para filtrar colecciones (y realizar otras transformaciones). Esta biblioteca permite realizar consultas similares a SQL sobre los objetos con fluidez sintaxis. Su , donde función acepta un calback con dos argumentos: un valor y una clave. Por ejemplo:

    $filtered = from($array)
        ->where(function ($v, $k) use ($allowed) {
            return in_array($k, $allowed);
        })
        ->toArray();

    (El where función devuelve un iterador, así que si usted sólo necesita iterar con foreach sobre la secuencia resultante, una vez, ->toArray() puede ser retirado).

    * desarrollado por mí

  10. 1

    matriz de filtro de la función de php:

    array_filter ( $array, $callback_function, $flag )

    $matriz es la matriz de entrada

    $callback_function – La función de devolución de llamada para utilizar, Si la función de devolución de llamada verdadero, el valor actual de la matriz se devuelve en la matriz de resultado.

    $indicador – es parámetro opcional, determinará en qué argumentos se envían a la función de devolución de llamada. Si este parámetro está vacío entonces la función de devolución de llamada se toman valores de matriz como argumento. Si desea enviar clave del array como argumento a continuación, utilice $bandera como ARRAY_FILTER_USE_KEY. Si desea enviar las claves y valores que debe utilizar $bandera como ARRAY_FILTER_USE_BOTH .

    Por Ejemplo : Considere la posibilidad de una matriz simple

    $array = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);

    Si quieres matriz de filtro basado en el clave del array, necesitamos utilizar ARRAY_FILTER_USE_KEY como tercer parámetro de la matriz de la función array_filter.

    $get_key_res = array_filter($array,"get_key",ARRAY_FILTER_USE_KEY );

    Si quieres matriz de filtro basado en el matriz de clave y valor de matriz, necesitamos utilizar ARRAY_FILTER_USE_BOTH como tercer parámetro de la función de matriz array_filter.

    $get_both = array_filter($array,"get_both",ARRAY_FILTER_USE_BOTH );

    Ejemplo de funciones de devolución de llamada:

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

    Que es la salida

    Output of $get_key is :Array ( [a] => 1 ) 
    Output of $get_both is :Array ( [a] => 1 ) 
  11. 0

    Con esta función usted puede filtrar una matriz multidimensional

    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];
    
    }
    • Este es el más feo de código que he visto en un tiempo.
  12. 0
    //Filter out array elements with keys shorter than 4 characters 
    //By using Anonymous function with  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($output);

    PHP: Cómo utilizar array_filter() a la matriz de filtro de llaves?

  13. -1
    $elements_array = ['first', 'second'];

    función para eliminar algunos de los elementos de la matriz de

    function remove($arr, $data) {
        return array_filter($arr, function ($element) use ($data) {
            return $element != $data;
        });
    }

    de llamada y de impresión

    print_r(remove($elements_array, 'second'));

    el resultado
    Array ( [0] => first )

    • La pregunta era sobre el filtrado de claves del array de valores.

Dejar respuesta

Please enter your comment!
Please enter your name here