Função in_array que não diferencia maiúsculas de minúsculas do PHP

131

É possível fazer comparação sem distinção entre maiúsculas e minúsculas ao usar a in_arrayfunção?

Portanto, com uma matriz de origem como esta:

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

As seguintes pesquisas retornariam verdadeiras:

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

Que função ou conjunto de funções faria o mesmo? Eu não acho que in_arrayele próprio possa fazer isso.

leepowers
fonte

Respostas:

101

você pode usar preg_grep():

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

print_r( preg_grep( "/ONe/i" , $a ) );
ghostdog74
fonte
37
usando expressões regulares não é uma boa solução, porque ele pode ser lento ... talvez array_map é mais rápido
phil-off
5
Para torná-lo um substituto para in_array, retornando um bool, torna-se: count(preg_grep('/^'.preg_quote($needle).'/$',$a)>0). Não é tão elegante, então. (Observe que os caracteres ^ e $ são necessários, a menos que a correspondência parcial seja desejada.) No entanto, se você realmente deseja que as entradas correspondentes sejam retornadas, eu gosto desta solução.
Darren Cook
2
O último comentário contém um erro de sintaxe: / $ deve ser $ /.
Gogowitsch 12/12/12
1
@DarrenCook, tanto quanto eu sei que um elenco bool também funcionaria (bool) preg_grep ('/ ^'. Preg_quote ($ needle). '$ /', $ A), como uma matriz vazia seria lançada como falsa
arraintxo
8
Parece que o caminho mais fácil é apenas converter em minúsculas.
27714 Joshua Dance
229

O óbvio é apenas converter o termo de pesquisa para minúsculo:

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

é claro que, se houver letras maiúsculas na matriz, você precisará fazer isso primeiro:

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

e procure isso. Não faz sentido fazerstrtolower em toda a matriz a cada pesquisa.

A pesquisa de matrizes, no entanto, é linear. Se você tem uma matriz grande ou vai fazer muito isso, seria melhor colocar os termos de pesquisa na chave da matriz, pois isso será um acesso muito mais rápido:

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

então

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

O único problema aqui é que as chaves do array devem ser únicas; portanto, se você tiver uma colisão (por exemplo, "Um" e "um"), perderá todos, exceto um.

cleto
fonte
23
Essa deve ser a resposta aceita. A adição de expressões regulares às vezes causa apenas 2 problemas.
27714 Joshua Dance
1
Aqui array_flip não seria uma solução ainda mais rápida, em vez de array_combine? $ search_array = array_flip (array_map ('strtolower', $ a));
jakub_jo
uma linha: in_array (strtolower ($ word), array_map ('strtolower', $ array))
Andrew Andrew
1
@Akira Yamamoto - o que há com a edição "fix syntax" ? Não temos permissão para corrigir código aqui. Eu rolei de volta.
Funk Quarenta Niner
Ou 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));
}

Da documentação

Tyler Carter
fonte
3
Você deve bloquear o código de citação (ou qualquer coisa realmente) que obtiver de outro lugar.
Cletus
3
Só para ficar claro. Não é uma crítica. Apenas uma sugestão (e apenas minha opinião, nada oficial). :) Pelo menos, se eu copiar um trecho de código de uma página, bloqueará a citação.
cletus
3
Além disso, o uso de um bloco de código o descreve melhor, pois é 'código'. A citação por bloco não permite que seja formatada corretamente.
Tyler Carter
Estou corrigido, depois de usar o botão real para adicionar >a cada linha, ele funciona. Estou acostumado a colocar manualmente >a primeira linha.
Tyler Carter
Estou acostumado a usar ctrl-Q para fazer isso. Isso tem um problema com os blocos de código porque, por algum motivo, quebra as linhas. Não me pergunte o porquê. Mas você pode corrigir isso ou colocar manualmente um >no início de cada linha.
Cletus
50
function in_arrayi($needle, $haystack) {
    return in_array(strtolower($needle), array_map('strtolower', $haystack));
}

Fonte: página de manual php.net in_array.

Gazler
fonte
Se você souber o que está na matriz, poderá deixar de fora o array_map; mas este é um bom exemplo.
Don
2
Na verdade eu fiz. Porque o mapeamento da matriz em todas as chamadas é ridículo.
Cletus
Além disso, supondo que (como Chacha) isso seja direto dos documentos, é melhor bloquear a citação.
Cletus
10

Digamos que você queira usar o in_array, eis como você pode tornar a pesquisa insensitiva.

In_array () que não diferencia maiúsculas de minúsculas:

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

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

}

Diferencia maiúsculas de minúsculas:

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

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

     {
        echo "found";
     }

}
Mike Q
fonte
2

O exposto acima está correto se assumirmos que matrizes podem conter apenas cadeias, mas matrizes também podem conter outras matrizes. Também a função in_array () pode aceitar uma matriz para $ needle, portanto, strtolower ($ needle) não funcionará se $ needle for uma matriz e array_map ('strtolower', $ haystack) não funcionará se $ haystack contiver outras matrizes, mas resultará em "Aviso do PHP: strtolower () espera que o parâmetro 1 seja string, dado a matriz".

Exemplo:

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

Então, eu criei uma classe auxiliar com os métodos relevantes, para fazer verificações in_array () com diferenciação de maiúsculas e minúsculas. Também estou usando mb_strtolower () em vez de strtolower (), para que outras codificações possam ser usadas. Aqui está o 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
fonte
1

Eu escrevi uma função simples para verificar se há um valor insensível em uma matriz, o código está abaixo.

função:

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

Como usar:

$array = array('one', 'two', 'three', 'four');
var_dump(in_array_insensitive('fOUr', $array));
Jake
fonte
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
fonte
Finalmente. Demorou 8 anos antes que alguém intensificasse e fornecesse a técnica mais eficiente - uma antecipaçãoreturn . Quando é necessário encontrar apenas 1 da agulha, não faz sentido continuar iterando depois de encontrá-la. Eu consertava um erro de digitação, assava o conceito $ strict e fazia alguns refinamentos, talvez algo próximo a 3v4l.org/WCTi2 . Este post não é perfeito, mas seu coração está no lugar certo.
Mckmackusa 22/08/19
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
fonte
1
Por favor, adicione uma descrição da solução que você está propondo.
il_raffa
-2
  • in_array aceita estes parâmetros: in_array (pesquisa, matriz, tipo)
  • se o parâmetro de pesquisa for uma sequência e o parâmetro de tipo estiver definido como TRUE, a pesquisa diferencia maiúsculas de minúsculas.
  • portanto, para fazer com que a pesquisa ignore o caso, seria suficiente usá-lo assim:

$ a = array ('um', 'dois', 'três', 'quatro');

$ b = matriz_inicial ('ONE', $ a, false);

user1077915
fonte
6
O terceiro parâmetro controla se o tipo da variável está marcado ou não, não o caso . Quando truecomparações estritas de tipo serão usadas, por exemplo '1' !== 1. Quando o falsemalabarismo de tipo será usado, por exemplo '1' == 1. Veja php.net/in_array e php.net/manual/en/types.comparisons.php para obter documentação.
leepowers