Función PHP in_array sensible a mayúsculas y minúsculas

131

¿Es posible hacer una comparación entre mayúsculas y minúsculas al usar la in_arrayfunción?

Entonces, con una matriz fuente como esta:

$a= array(
 'one',
 'two',
 'three',
 'four'
);

Las siguientes búsquedas volverían todas verdaderas:

in_array('one', $a);
in_array('two', $a);
in_array('ONE', $a);
in_array('fOUr', $a);

¿Qué función o conjunto de funciones haría lo mismo? No creo que in_arraypueda hacer esto.

potencias de sotavento
fuente

Respuestas:

101

puedes usar preg_grep():

$a= array(
 'one',
 'two',
 'three',
 'four'
);

print_r( preg_grep( "/ONe/i" , $a ) );
ghostdog74
fuente
37
el uso de expresiones regulares no es una buena solución, porque puede ser lento ... tal vez array_map es más rápido
phil-opp
55
Para que sea un reemplazo directo para in_array, devolver un bool, se convierte en: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). No tan elegante, entonces. (Observe que los caracteres ^ y $ son obligatorios, a menos que se desee una coincidencia parcial). Sin embargo, si realmente desea que se devuelvan las entradas coincidentes, me gusta esta solución.
Darren Cook, el
2
El último comentario contiene un error de sintaxis: / $ debería ser $ / en su lugar.
Gogowitsch
1
@DarrenCook, por lo que sé, un bool cast también funcionaría (bool) preg_grep ('/ ^'. Preg_quote ($ needle). '$ /', $ A), ya que una matriz vacía se convertiría en falso
arraintxo
8
Parece que la forma más fácil de hacerlo es simplemente convertir a minúsculas.
Joshua Dance
229

Lo obvio es simplemente convertir el término de búsqueda a minúsculas:

if (in_array(strtolower($word), $array)) { 
  ...

por supuesto, si hay letras mayúsculas en la matriz, primero deberá hacer esto:

$search_array = array_map('strtolower', $array);

y busca eso. No tiene sentido hacer strtolowertodo el conjunto con cada búsqueda.

Sin embargo, la búsqueda de matrices es lineal. Si tiene una matriz grande o va a hacer esto mucho, sería mejor poner los términos de búsqueda en la clave de la matriz, ya que este será un acceso mucho más rápido:

$search_array = array_combine(array_map('strtolower', $a), $a);

luego

if ($search_array[strtolower($word)]) { 
  ...

El único problema aquí es que las claves de matriz deben ser únicas, por lo que si tiene una colisión (por ejemplo, "Una" y "una") perderá todas menos una.

cletus
fuente
23
Esta debería ser la respuesta aceptada. Agregar expresiones regulares a veces solo genera 2 problemas.
Joshua Dance
1
¿No sería array_flip aquí una solución aún más rápida, en lugar de array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo
una línea: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrew
1
@ Akira Yamamoto: ¿qué pasa con la edición "corregir sintaxis" ? No se nos permite corregir el código aquí. Lo hice retroceder.
Funk Forty Niner el
O use array_change_key_case () secure.php.net/manual/en/function.array-change-key-case.php
boctulus
113
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

De la documentación

Tyler Carter
fuente
3
Debe bloquear el código de cotización (o cualquier cosa realmente) que obtenga de otro lugar.
cletus
3
Para ser claro. No es una crítica. Solo una sugerencia (y solo mi opinión, nada oficial). :) Al menos si copio un fragmento de código de una página, bloquearé la cita.
cletus
3
Además, usar un bloque de código lo describe mejor, ya que es 'código'. La cita en bloque no permite que se formatee correctamente.
Tyler Carter
Estoy corregido, después de usar el botón real para agregar >a cada línea, funciona. Estoy acostumbrado a poner manualmente el >en la primera línea.
Tyler Carter
Estoy acostumbrado a usar ctrl-Q para hacerlo. Eso tiene un problema con los bloques de código porque por alguna razón envuelve líneas. No me preguntes por qué. Pero puede corregir eso o poner manualmente un >al comienzo de cada línea.
cletus
50
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Fuente: página del manual php.net in_array.

Gazler
fuente
Si sabe lo que hay en la matriz, puede omitir la matriz_mapa; Pero este es un buen ejemplo.
Don
2
En realidad lo hice. Porque mapear la matriz en cada llamada es, bueno, ridículo.
cletus
Además, suponiendo (como Chacha) que esto viene directamente de los documentos, es mejor bloquearlo entre comillas.
cletus
10

Supongamos que quiere usar el in_array, así es cómo puede hacer que el caso de búsqueda no sea sensible.

Mayúsculas y minúsculas en_array ():

foreach($searchKey as $key => $subkey) {

     if (in_array(strtolower($subkey), array_map("strtolower", $subarray)))
     {
        echo "found";
     }

}

Mayúsculas y minúsculas normales:

foreach($searchKey as $key => $subkey) {

if (in_array("$subkey", $subarray))

     {
        echo "found";
     }

}
Mike Q
fuente
2

Lo anterior es correcto si suponemos que las matrices pueden contener solo cadenas, pero las matrices también pueden contener otras matrices. Además, la función in_array () puede aceptar una matriz para $ needle, por lo que strtolower ($ needle) no funcionará si $ needle es una matriz y array_map ('strtolower', $ haystack) no funcionará si $ haystack contiene otro matrices, pero dará como resultado "Advertencia de PHP: strtolower () espera que el parámetro 1 sea una cadena, matriz dada".

Ejemplo:

$needle = array('p', 'H');
$haystack = array(array('p', 'H'), 'U');

Así que creé una clase auxiliar con los métodos relevantes, para hacer comprobaciones in_array () sensibles a mayúsculas y minúsculas. También estoy usando mb_strtolower () en lugar de strtolower (), por lo que se pueden usar otras codificaciones. Aquí está el código:

class StringHelper {

public static function toLower($string, $encoding = 'UTF-8')
{
    return mb_strtolower($string, $encoding);
}

/**
 * Digs into all levels of an array and converts all string values to lowercase
 */
public static function arrayToLower($array)
{
    foreach ($array as &$value) {
        switch (true) {
            case is_string($value):
                $value = self::toLower($value);
                break;
            case is_array($value):
                $value = self::arrayToLower($value);
                break;
        }
    }
    return $array;
}

/**
 * Works like the built-in PHP in_array() function — Checks if a value exists in an array, but
 * gives the option to choose how the comparison is done - case-sensitive or case-insensitive
 */
public static function inArray($needle, $haystack, $case = 'case-sensitive', $strict = false)
{
    switch ($case) {
        default:
        case 'case-sensitive':
        case 'cs':
            return in_array($needle, $haystack, $strict);
            break;
        case 'case-insensitive':
        case 'ci':
            if (is_array($needle)) {
                return in_array(self::arrayToLower($needle), self::arrayToLower($haystack), $strict);
            } else {
                return in_array(self::toLower($needle), self::arrayToLower($haystack), $strict);
            }
            break;
    }
}
}
Alex
fuente
1

Escribí una función simple para verificar un valor insensible en una matriz, el código está debajo.

función:

function in_array_insensitive($needle, $haystack) {
   $needle = strtolower($needle);
   foreach($haystack as $k => $v) {
      $haystack[$k] = strtolower($v);
   }
   return in_array($needle, $haystack);
}

cómo utilizar:

$array = array('one', 'two', 'three', 'four');
var_dump(in_array_insensitive('fOUr', $array));
Jake
fuente
1
/**
 * in_array function variant that performs case-insensitive comparison when needle is a string.
 *
 * @param mixed $needle
 * @param array $haystack
 * @param bool $strict
 *
 * @return bool
 */
function in_arrayi($needle, array $haystack, bool $strict = false): bool
{

    if (is_string($needle)) {

        $needle = strtolower($needle);

        foreach ($haystack as $value) {

            if (is_string($value)) {
                if (strtolower($value) === $needle) {
                    return true;
                }
            }

        }

        return false;

    }

    return in_array($needle, $haystack, $strict);

}


/**
 * in_array function variant that performs case-insensitive comparison when needle is a string.
 * Multibyte version.
 *
 * @param mixed $needle
 * @param array $haystack
 * @param bool $strict
 * @param string|null $encoding
 *
 * @return bool
 */
function mb_in_arrayi($needle, array $haystack, bool $strict = false, ?string $encoding = null): bool
{

    if (null === $encoding) {
        $encoding = mb_internal_encoding();
    }

    if (is_string($needle)) {

        $needle = mb_strtolower($needle, $encoding);

        foreach ($haystack as $value) {

            if (is_string($value)) {
                if (mb_strtolower($value, $encoding) === $needle) {
                    return true;
                }
            }

        }

        return false;

    }

    return in_array($needle, $haystack, $strict);

}
Carlos Coelho
fuente
Finalmente. Pasaron 8 años antes de que alguien interviniera y proporcionara la técnica más eficiente, una tempranareturn . Cuando solo se necesita encontrar 1 de la aguja, no tiene sentido seguir iterando después de encontrarla. Sin embargo, corregiría un error tipográfico, hornearía el concepto $ estricto y realizaría algunos ajustes , tal vez algo cercano a 3v4l.org/WCTi2 . Esta publicación no es perfecta, pero su corazón está en el lugar correcto.
mickmackusa
0
$a = [1 => 'funny', 3 => 'meshgaat', 15 => 'obi', 2 => 'OMER'];  

$b = 'omer';

function checkArr($x,$array)
{
    $arr = array_values($array);
    $arrlength = count($arr);
    $z = strtolower($x);

    for ($i = 0; $i < $arrlength; $i++) {
        if ($z == strtolower($arr[$i])) {
            echo "yes";
        }  
    } 
};

checkArr($b, $a);
omer
fuente
1
Por favor, agregue una descripción de la solución que está proponiendo.
il_raffa
-2
  • in_array acepta estos parámetros: in_array (búsqueda, matriz, tipo)
  • si el parámetro de búsqueda es una cadena y el parámetro de tipo se establece en TRUE, la búsqueda distingue entre mayúsculas y minúsculas.
  • para que la búsqueda ignore el caso, sería suficiente usarlo así:

$ a = array ('uno', 'dos', 'tres', 'cuatro');

$ b = en_array ('UNO', $ a, falso);

usuario1077915
fuente
66
El tercer parámetro controla si se verifica o no el tipo de variable, no el caso . Cuando truese utilizarán comparaciones de tipo estrictas, p '1' !== 1. Ej . Cuando falsese utilizará el tipo malabarismo, p '1' == 1. Ej . Consulte php.net/in_array y php.net/manual/en/types.comparisons.php para obtener documentación.
leepowers