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-?


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

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

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

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


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

14
foreach($arr as $key => $value)
{
   if(preg_match('/^foo-/', $key))
   {
        // You can access $value or create a new array based off these values
   }
}

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í.


¿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
)
*/

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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.