PHP: obtenga todas las claves de una matriz que comience con una determinada cadena

84

Tengo una matriz que se parece a esto:

array(
  'abc' => 0,
  'foo-bcd' => 1,
  'foo-def' => 1,
  'foo-xyz' => 0,
  // ...
)

¿Cómo puedo obtener solo los elementos que comienzan con foo-?

Alex
fuente
3
Tener una matriz con prefijos como este es un olor a código. Extraiga esos valores en un objeto que contenga estos valores o al menos haga que el prefijo apunte a una matriz y agregue los valores.
Gordon

Respuestas:

20
$arr_main_array = array('foo-test' => 123, 'other-test' => 456, 'foo-result' => 789);

foreach($arr_main_array as $key => $value){
    $exp_key = explode('-', $key);
    if($exp_key[0] == 'foo'){
         $arr_result[] = $value;
    }
}

if(isset($arr_result)){
    print_r($arr_result);
}
Desarrollador-Sid
fuente
18
Antes de tomar esta solución, la siguiente es mejor. Nunca use funciones de matriz donde la función de cadena simple será suficiente. Las funciones de cadena son MUCHO más rápidas. Esto se 'retrasará' con matrices grandes.
Martijn
2
No veo el punto de explotar las claves de matriz en matrices. Son cadenas y la pregunta original es solo sobre un prefijo de cadena. Además, OP solicita "los elementos" en lugar de solo los valores, por lo que el resultado indexado numéricamente será inútil: las claves son claramente importantes aquí, y los valores son (presumiblemente) banderas 1/0 anónimas.
Jason
126

Enfoque funcional:

Elija una array_filter_keyespecie de función de los comentarios en http://php.net/array_filter o escriba la suya propia. Entonces podrías hacer:

$array = array_filter_key($array, function($key) {
    return strpos($key, 'foo-') === 0;
});

Enfoque procedimental:

$only_foo = array();
foreach ($array as $key => $value) {
    if (strpos($key, 'foo-') === 0) {
        $only_foo[$key] = $value;
    }
}

Enfoque procedimental utilizando objetos:

$i = new ArrayIterator($array);
$only_foo = array();
while ($i->valid()) {
    if (strpos($i->key(), 'foo-') === 0) {
        $only_foo[$i->key()] = $i->current();
    }
    $i->next();
}
erisco
fuente
20
Nota PHP 5.6 agrega el indicador ARRAY_FILTER_USE_KEY a array_filter(), que puede usar en lugar de proporcionar una array_filter_key()función personalizada .
Jason
4
¿Puede agregar la función array_filter_key a su ejemplo? Seguí recibiendo un error y tuve que volver a leer tu publicación varias veces antes de reconocer mi error. No es difícil publicar el código, guardar un clic y ahorrarle tiempo a alguien en la resolución de problemas. Gracias.
Chris Sprague
38

Así es como lo haría yo, aunque no puedo darte un consejo más eficaz antes de entender qué quieres hacer con los valores que obtienes.

$search = "foo-";
$search_length = strlen($search);
foreach ($array as $key => $value) {
    if (substr($key, 0, $search_length) == $search) {
        ...use the $value...
    }
}
Matías Cánepa
fuente
2
También puede utilizar:foreach ($array as $key => $value) { if (0 === strpos($key, 'foo-')) { ...use the $value... } }
Iago
El "4" aquí debe ajustarse a la longitud que tenga "foo-".
Jason
21

Simplemente utilicé la array_filterfunción para lograr la solución de la siguiente manera

<?php

$input = array(
    'abc' => 0,
    'foo-bcd' => 1,
    'foo-def' => 1,
    'foo-xyz' => 0,
);

$filtered = array_filter($input, function ($key) {
    return strpos($key, 'foo-') === 0;
}, ARRAY_FILTER_USE_KEY);

print_r($filtered);

Salida

Array
(
    [foo-bcd] => 1
    [foo-def] => 1
    [foo-xyz] => 0
)

Para verificación en vivo https://3v4l.org/lJCse

Suresh Velusamy
fuente
1
Preste atención a que esto necesita al menos PHP 5.6.0 (debido al uso de la constante ARRAY_FILTER_USE_KEY). En versiones anteriores, puede usar: [código]
Netsurfer
20

Desde PHP 5.3 puedes usar la preg_filterfunción: aquí

$unprefixed_keys = preg_filter('/^foo-(.*)/', '$1', array_keys( $arr ));

// Result:
// $unprefixed_keys === array('bcd','def','xyz')
biziclop
fuente
14
foreach($arr as $key => $value)
{
   if(preg_match('/^foo-/', $key))
   {
        // You can access $value or create a new array based off these values
   }
}
Tim Cooper
fuente
3
Una expresión regular no es realmente necesaria en este caso. El método substr es un poco más eficiente
jfoucher
2
@jfoucher: Eso es cierto, sin embargo, personalmente, es más fácil de leer.
Tim Cooper
2
Puede ser más flexible, pero tiene el costo de tener que escapar de los caracteres especiales preg si no desea hacer una coincidencia de expresión regular. Así que utilícelo con precaución. Le sugiero que use RE solo si necesita RE.
Jason
7

Modificación del enfoque funcional de erisco ,

array_filter($signatureData[0]["foo-"], function($k) {
    return strpos($k, 'foo-abc') === 0;
}, ARRAY_FILTER_USE_KEY);

esto funcionó para mí.

Keyur
fuente
¿Alguna diferencia en rendimiento o utilidad en comparación con la versión array_filter_key proporcionada por @erisco?
Jeffrey the Giraffe
No Supongo que no debería haber ninguna diferencia en el rendimiento. @MaciekSemik
Keyur
1
Esta es una función básica de PHP, por lo que debería preferirse.
Jeremy John
3

Además de la respuesta de @Suresh Velusamy anterior (que necesita al menos PHP 5.6.0), puede usar lo siguiente si tiene una versión anterior de PHP:

<?php

$input = array(
    'abc' => 0,
    'foo-bcd' => 1,
    'foo-def' => 1,
    'foo-xyz' => 0,
);

$filtered = array_filter(array_keys($input), function($key) {
    return strpos($key, 'foo-') === 0;
});

print_r($filtered);

/* Output:
Array
(
    [1] => foo-bcd
    [2] => foo-def
    [3] => foo-xyz
)
// the numerical array keys are the position in the original array!
*/

// if you want your array newly numbered just add:
$filtered = array_values($filtered);

print_r($filtered);

/* Output:
Array
(
    [0] => foo-bcd
    [1] => foo-def
    [2] => foo-xyz
)
*/
Netsurfer
fuente
Tenga en cuenta (o al menos para mí) que esto solo devuelve las claves de matriz que coinciden. La respuesta a continuación de @ suresh-velusamy extrae la matriz real con el $key => $valuepar original . Se indica en la salida de esta respuesta, pero aún no se mencionó explícitamente
Martie